@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.
- package/dist/chunk-index.cjs.js +29 -55
- package/dist/chunk-index.cjs2.js +84 -0
- package/dist/chunk-index.es.js +24 -50
- package/dist/chunk-index.es2.js +82 -0
- package/dist/funnelfox-billing.cjs.js +293 -112
- package/dist/funnelfox-billing.esm.js +293 -112
- package/dist/funnelfox-billing.js +397 -164
- package/dist/funnelfox-billing.min.js +1 -1
- package/package.json +2 -2
- package/src/types.d.ts +56 -25
|
@@ -213,7 +213,7 @@ var PaymentMethod;
|
|
|
213
213
|
/**
|
|
214
214
|
* @fileoverview Constants for Funnefox SDK
|
|
215
215
|
*/
|
|
216
|
-
const SDK_VERSION = '0.
|
|
216
|
+
const SDK_VERSION = '0.5.0-beta.1';
|
|
217
217
|
const DEFAULTS = {
|
|
218
218
|
BASE_URL: 'https://billing.funnelfox.com',
|
|
219
219
|
REGION: 'default',
|
|
@@ -240,9 +240,11 @@ const EVENTS = {
|
|
|
240
240
|
INPUT_ERROR: 'input-error',
|
|
241
241
|
LOADER_CHANGE: 'loader-change',
|
|
242
242
|
METHOD_RENDER: 'method-render',
|
|
243
|
+
METHOD_RENDER_ERROR: 'method-render-error',
|
|
243
244
|
START_PURCHASE: 'start-purchase',
|
|
244
245
|
PURCHASE_FAILURE: 'purchase-failure',
|
|
245
246
|
PURCHASE_COMPLETED: 'purchase-completed',
|
|
247
|
+
PURCHASE_CANCELLED: 'purchase-cancelled',
|
|
246
248
|
};
|
|
247
249
|
const API_ENDPOINTS = {
|
|
248
250
|
CREATE_CLIENT_SESSION: '/v1/checkout/create_client_session',
|
|
@@ -318,10 +320,6 @@ class PrimerWrapper {
|
|
|
318
320
|
const primerOptions = merge({
|
|
319
321
|
paymentHandling: 'MANUAL',
|
|
320
322
|
apiVersion: '2.4',
|
|
321
|
-
paypal: {
|
|
322
|
-
buttonColor: 'blue',
|
|
323
|
-
paymentFlow: 'PREFER_VAULT',
|
|
324
|
-
},
|
|
325
323
|
}, options);
|
|
326
324
|
try {
|
|
327
325
|
const headless = await window.Primer.createHeadless(clientToken, primerOptions);
|
|
@@ -349,9 +347,64 @@ class PrimerWrapper {
|
|
|
349
347
|
this.paymentMethodsInterfaces[method].setDisabled(disabled);
|
|
350
348
|
}
|
|
351
349
|
}
|
|
352
|
-
async
|
|
350
|
+
async renderButton(allowedPaymentMethod, { container, }) {
|
|
351
|
+
const containerEl = this.validateContainer(container);
|
|
352
|
+
let button;
|
|
353
|
+
this.ensurePrimerAvailable();
|
|
354
|
+
if (!this.headless) {
|
|
355
|
+
throw new PrimerError('Headless checkout not found');
|
|
356
|
+
}
|
|
357
|
+
try {
|
|
358
|
+
const pmManager = await this.headless.createPaymentMethodManager(allowedPaymentMethod);
|
|
359
|
+
if (!pmManager) {
|
|
360
|
+
throw new Error('Payment method manager is not available');
|
|
361
|
+
}
|
|
362
|
+
button = pmManager.createButton();
|
|
363
|
+
await button.render(containerEl, {});
|
|
364
|
+
this.destroyCallbacks.push(() => button.clean());
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
throw new PrimerError('Failed to initialize Primer checkout', error);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
async initMethod(method, htmlNode, options) {
|
|
371
|
+
if (method === PaymentMethod.PAYMENT_CARD) {
|
|
372
|
+
if (!options.cardElements ||
|
|
373
|
+
!options.onSubmit ||
|
|
374
|
+
!options.onInputChange) {
|
|
375
|
+
throw new PrimerError('Card elements, onSubmit, and onInputChange are required for PAYMENT_CARD method');
|
|
376
|
+
}
|
|
377
|
+
return this.renderCardCheckoutWithElements(options.cardElements, {
|
|
378
|
+
onSubmit: options.onSubmit,
|
|
379
|
+
onInputChange: options.onInputChange,
|
|
380
|
+
onMethodRenderError: options.onMethodRenderError,
|
|
381
|
+
onMethodRender: options.onMethodRender,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
// For button methods, render directly into htmlNode
|
|
386
|
+
this.ensurePrimerAvailable();
|
|
387
|
+
if (!this.headless) {
|
|
388
|
+
throw new PrimerError('Headless checkout not found');
|
|
389
|
+
}
|
|
390
|
+
try {
|
|
391
|
+
const pmManager = await this.headless.createPaymentMethodManager(method);
|
|
392
|
+
if (!pmManager) {
|
|
393
|
+
throw new Error('Payment method manager is not available');
|
|
394
|
+
}
|
|
395
|
+
const button = pmManager.createButton();
|
|
396
|
+
await button.render(htmlNode, {});
|
|
397
|
+
this.destroyCallbacks.push(() => button.clean());
|
|
398
|
+
options.onMethodRender(method);
|
|
399
|
+
}
|
|
400
|
+
catch (error) {
|
|
401
|
+
options.onMethodRenderError(method);
|
|
402
|
+
throw new PrimerError('Failed to initialize Primer checkout', error);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
async renderCardCheckoutWithElements(elements, { onSubmit, onInputChange, onMethodRenderError, onMethodRender, }) {
|
|
353
407
|
try {
|
|
354
|
-
const elements = this.initializeCardElements(cardSelectors);
|
|
355
408
|
const pmManager = await this.headless.createPaymentMethodManager('PAYMENT_CARD');
|
|
356
409
|
if (!pmManager) {
|
|
357
410
|
throw new Error('Payment method manager is not available');
|
|
@@ -398,7 +451,7 @@ class PrimerWrapper {
|
|
|
398
451
|
onSubmit(false);
|
|
399
452
|
}
|
|
400
453
|
};
|
|
401
|
-
elements.button
|
|
454
|
+
elements.button?.addEventListener('click', onSubmitHandler);
|
|
402
455
|
await Promise.all([
|
|
403
456
|
cardNumberInput.render(elements.cardNumber, {
|
|
404
457
|
placeholder: '1234 1234 1234 1234',
|
|
@@ -416,10 +469,13 @@ class PrimerWrapper {
|
|
|
416
469
|
style: inputStyle,
|
|
417
470
|
}),
|
|
418
471
|
]);
|
|
419
|
-
|
|
472
|
+
const onDestroy = () => {
|
|
420
473
|
pmManager.removeHostedInputs();
|
|
421
474
|
elements.cardholderName.removeEventListener('change', cardHolderOnChange);
|
|
422
|
-
|
|
475
|
+
elements.button.removeEventListener('click', onSubmitHandler);
|
|
476
|
+
};
|
|
477
|
+
this.destroyCallbacks.push(onDestroy);
|
|
478
|
+
onMethodRender(PaymentMethod.PAYMENT_CARD);
|
|
423
479
|
return {
|
|
424
480
|
setDisabled: (disabled) => {
|
|
425
481
|
cardNumberInput.setDisabled(disabled);
|
|
@@ -427,38 +483,22 @@ class PrimerWrapper {
|
|
|
427
483
|
cvvInput.setDisabled(disabled);
|
|
428
484
|
elements.button.disabled = disabled;
|
|
429
485
|
},
|
|
486
|
+
submit: () => onSubmitHandler(),
|
|
487
|
+
destroy: () => {
|
|
488
|
+
this.destroyCallbacks = this.destroyCallbacks.filter(callback => callback !== onDestroy);
|
|
489
|
+
onDestroy();
|
|
490
|
+
},
|
|
430
491
|
};
|
|
431
492
|
}
|
|
432
493
|
catch (error) {
|
|
433
494
|
throw new PrimerError('Failed to initialize Primer checkout', error);
|
|
434
495
|
}
|
|
435
496
|
}
|
|
436
|
-
async
|
|
437
|
-
const containerEl = this.validateContainer(container);
|
|
438
|
-
let button;
|
|
439
|
-
this.ensurePrimerAvailable();
|
|
440
|
-
if (!this.headless) {
|
|
441
|
-
throw new PrimerError('Headless checkout not found');
|
|
442
|
-
}
|
|
443
|
-
try {
|
|
444
|
-
const pmManager = await this.headless.createPaymentMethodManager(allowedPaymentMethod);
|
|
445
|
-
if (!pmManager) {
|
|
446
|
-
throw new Error('Payment method manager is not available');
|
|
447
|
-
}
|
|
448
|
-
button = pmManager.createButton();
|
|
449
|
-
await button.render(containerEl, {});
|
|
450
|
-
this.destroyCallbacks.push(() => button.clean());
|
|
451
|
-
}
|
|
452
|
-
catch (error) {
|
|
453
|
-
throw new PrimerError('Failed to initialize Primer checkout', error);
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
async renderCheckout(clientToken, options) {
|
|
457
|
-
const { cardSelectors, paymentButtonSelectors, container, onTokenizeSuccess, onResumeSuccess, onSubmit, onInputChange, onMethodRender, ...restPrimerOptions } = options;
|
|
497
|
+
async initializeHeadlessCheckout(clientToken, primerOptions) {
|
|
458
498
|
await this.createHeadlessCheckout(clientToken, {
|
|
459
|
-
...
|
|
460
|
-
onTokenizeSuccess: this.wrapTokenizeHandler(onTokenizeSuccess),
|
|
461
|
-
onResumeSuccess: this.wrapResumeHandler(onResumeSuccess),
|
|
499
|
+
...primerOptions,
|
|
500
|
+
onTokenizeSuccess: this.wrapTokenizeHandler(primerOptions.onTokenizeSuccess),
|
|
501
|
+
onResumeSuccess: this.wrapResumeHandler(primerOptions.onResumeSuccess),
|
|
462
502
|
onAvailablePaymentMethodsLoad: (items) => {
|
|
463
503
|
let isApplePayAvailable = false;
|
|
464
504
|
this.availableMethods = ALLOWED_PAYMENT_METHODS.filter(method => {
|
|
@@ -477,25 +517,33 @@ class PrimerWrapper {
|
|
|
477
517
|
}
|
|
478
518
|
},
|
|
479
519
|
});
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
onInputChange,
|
|
485
|
-
};
|
|
520
|
+
}
|
|
521
|
+
async renderCheckout(clientToken, checkoutOptions, checkoutRenderOptions) {
|
|
522
|
+
const { cardElements, paymentButtonElements, container, onSubmit, onInputChange, onMethodRender, onMethodRenderError, } = checkoutRenderOptions;
|
|
523
|
+
await this.initializeHeadlessCheckout(clientToken, checkoutOptions);
|
|
486
524
|
for (const method of this.availableMethods) {
|
|
487
525
|
if (method === PaymentMethod.PAYMENT_CARD) {
|
|
488
|
-
|
|
489
|
-
|
|
526
|
+
// For card, use the main container
|
|
527
|
+
await this.initMethod(method, container, {
|
|
528
|
+
cardElements,
|
|
529
|
+
onSubmit,
|
|
530
|
+
onInputChange,
|
|
531
|
+
onMethodRender,
|
|
532
|
+
onMethodRenderError,
|
|
533
|
+
});
|
|
490
534
|
}
|
|
491
535
|
else {
|
|
492
|
-
const
|
|
493
|
-
|
|
494
|
-
:
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
536
|
+
const buttonElementsMap = {
|
|
537
|
+
[PaymentMethod.PAYPAL]: paymentButtonElements.paypal,
|
|
538
|
+
[PaymentMethod.GOOGLE_PAY]: paymentButtonElements.googlePay,
|
|
539
|
+
[PaymentMethod.APPLE_PAY]: paymentButtonElements.applePay,
|
|
540
|
+
};
|
|
541
|
+
// For buttons, use the specific button container element
|
|
542
|
+
const buttonElement = buttonElementsMap[method];
|
|
543
|
+
await this.initMethod(method, buttonElement, {
|
|
544
|
+
onMethodRender,
|
|
545
|
+
onMethodRenderError,
|
|
546
|
+
});
|
|
499
547
|
}
|
|
500
548
|
}
|
|
501
549
|
this.isInitialized = true;
|
|
@@ -756,6 +804,12 @@ class APIClient {
|
|
|
756
804
|
}
|
|
757
805
|
throw new APIError('Invalid payment response format', null, { response });
|
|
758
806
|
}
|
|
807
|
+
async oneClick(payload) {
|
|
808
|
+
return (await this.request(`/billing/${this.orgId}/v1/checkout/one_click`, {
|
|
809
|
+
method: 'POST',
|
|
810
|
+
body: JSON.stringify(payload),
|
|
811
|
+
}));
|
|
812
|
+
}
|
|
759
813
|
}
|
|
760
814
|
|
|
761
815
|
var loaderHtml = "<div class=\"ff-sdk-loader-container\">\n <div class=\"ff-sdk-loader\"></div>\n</div>\n";
|
|
@@ -799,6 +853,9 @@ class CheckoutInstance extends EventEmitter {
|
|
|
799
853
|
this.handleMethodRender = (method) => {
|
|
800
854
|
this.emit(EVENTS.METHOD_RENDER, method);
|
|
801
855
|
};
|
|
856
|
+
this.handleMethodRenderError = (method) => {
|
|
857
|
+
this.emit(EVENTS.METHOD_RENDER_ERROR, method);
|
|
858
|
+
};
|
|
802
859
|
this.handleSubmit = (isSubmitting) => {
|
|
803
860
|
this.onLoaderChangeWithRace(isSubmitting);
|
|
804
861
|
this._setState(isSubmitting ? 'processing' : 'ready');
|
|
@@ -871,9 +928,6 @@ class CheckoutInstance extends EventEmitter {
|
|
|
871
928
|
this.primerWrapper = new PrimerWrapper();
|
|
872
929
|
this.isDestroyed = false;
|
|
873
930
|
this._setupCallbackBridges();
|
|
874
|
-
this.initialize().then(() => {
|
|
875
|
-
this.checkoutConfig?.onInitialized?.();
|
|
876
|
-
});
|
|
877
931
|
}
|
|
878
932
|
_setupCallbackBridges() {
|
|
879
933
|
if (this.callbacks.onSuccess) {
|
|
@@ -896,25 +950,10 @@ class CheckoutInstance extends EventEmitter {
|
|
|
896
950
|
try {
|
|
897
951
|
this.showInitializingLoader();
|
|
898
952
|
this._setState('initializing');
|
|
899
|
-
this.
|
|
900
|
-
baseUrl: this.baseUrl || DEFAULTS.BASE_URL,
|
|
901
|
-
orgId: this.orgId,
|
|
902
|
-
timeout: DEFAULTS.REQUEST_TIMEOUT,
|
|
903
|
-
retryAttempts: DEFAULTS.RETRY_ATTEMPTS,
|
|
904
|
-
});
|
|
905
|
-
const sessionResponse = await this.apiClient.createClientSession({
|
|
906
|
-
priceId: this.checkoutConfig.priceId,
|
|
907
|
-
externalId: this.checkoutConfig.customer.externalId,
|
|
908
|
-
email: this.checkoutConfig.customer.email,
|
|
909
|
-
region: this.region || DEFAULTS.REGION,
|
|
910
|
-
clientMetadata: this.checkoutConfig.clientMetadata,
|
|
911
|
-
countryCode: this.checkoutConfig.customer.countryCode,
|
|
912
|
-
});
|
|
913
|
-
const sessionData = this.apiClient.processSessionResponse(sessionResponse);
|
|
914
|
-
this.orderId = sessionData.orderId;
|
|
915
|
-
this.clientToken = sessionData.clientToken;
|
|
953
|
+
await this.createSession();
|
|
916
954
|
await this._initializePrimerCheckout();
|
|
917
955
|
this._setState('ready');
|
|
956
|
+
this.checkoutConfig?.onInitialized?.();
|
|
918
957
|
return this;
|
|
919
958
|
}
|
|
920
959
|
catch (error) {
|
|
@@ -926,48 +965,97 @@ class CheckoutInstance extends EventEmitter {
|
|
|
926
965
|
this.hideInitializingLoader();
|
|
927
966
|
}
|
|
928
967
|
}
|
|
929
|
-
async
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
968
|
+
async createSession() {
|
|
969
|
+
this.apiClient = new APIClient({
|
|
970
|
+
baseUrl: this.baseUrl || DEFAULTS.BASE_URL,
|
|
971
|
+
orgId: this.orgId,
|
|
972
|
+
timeout: DEFAULTS.REQUEST_TIMEOUT,
|
|
973
|
+
retryAttempts: DEFAULTS.RETRY_ATTEMPTS,
|
|
974
|
+
});
|
|
975
|
+
const sessionResponse = await this.apiClient.createClientSession({
|
|
976
|
+
priceId: this.checkoutConfig.priceId,
|
|
977
|
+
externalId: this.checkoutConfig.customer.externalId,
|
|
978
|
+
email: this.checkoutConfig.customer.email,
|
|
979
|
+
region: this.region || DEFAULTS.REGION,
|
|
980
|
+
clientMetadata: this.checkoutConfig.clientMetadata,
|
|
981
|
+
countryCode: this.checkoutConfig.customer.countryCode,
|
|
982
|
+
});
|
|
983
|
+
const sessionData = this.apiClient.processSessionResponse(sessionResponse);
|
|
984
|
+
this.orderId = sessionData.orderId;
|
|
985
|
+
this.clientToken = sessionData.clientToken;
|
|
986
|
+
}
|
|
987
|
+
convertCardSelectorsToElements(selectors, container) {
|
|
988
|
+
const cardNumber = container.querySelector(selectors.cardNumber);
|
|
989
|
+
const expiryDate = container.querySelector(selectors.expiryDate);
|
|
990
|
+
const cvv = container.querySelector(selectors.cvv);
|
|
991
|
+
const cardholderName = container.querySelector(selectors.cardholderName);
|
|
992
|
+
const button = container.querySelector(selectors.button);
|
|
993
|
+
if (!cardNumber || !expiryDate || !cvv || !button) {
|
|
994
|
+
throw new CheckoutError('Required card input elements not found in container');
|
|
995
|
+
}
|
|
996
|
+
return {
|
|
997
|
+
cardNumber,
|
|
998
|
+
expiryDate,
|
|
999
|
+
cvv,
|
|
1000
|
+
cardholderName,
|
|
1001
|
+
button,
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
convertPaymentButtonSelectorsToElements(selectors) {
|
|
1005
|
+
const paypal = document.querySelector(selectors.paypal);
|
|
1006
|
+
const googlePay = document.querySelector(selectors.googlePay);
|
|
1007
|
+
const applePay = document.querySelector(selectors.applePay);
|
|
1008
|
+
if (!paypal || !googlePay || !applePay) {
|
|
1009
|
+
throw new CheckoutError('Required payment button elements not found in container');
|
|
1010
|
+
}
|
|
1011
|
+
return {
|
|
1012
|
+
paypal,
|
|
1013
|
+
googlePay,
|
|
1014
|
+
applePay,
|
|
957
1015
|
};
|
|
1016
|
+
}
|
|
1017
|
+
async _initializePrimerCheckout() {
|
|
1018
|
+
// Get container element
|
|
1019
|
+
const containerElement = this.getContainer();
|
|
1020
|
+
if (!containerElement) {
|
|
1021
|
+
throw new CheckoutError(`Checkout container not found: ${this.checkoutConfig.container}`);
|
|
1022
|
+
}
|
|
1023
|
+
// Get selectors (either from config or default skin)
|
|
1024
|
+
let cardElements;
|
|
1025
|
+
let paymentButtonElements;
|
|
1026
|
+
let checkoutOptions;
|
|
958
1027
|
if (!this.checkoutConfig.cardSelectors ||
|
|
959
1028
|
!this.checkoutConfig.paymentButtonSelectors) {
|
|
960
1029
|
if (this.checkoutConfig.paymentMethodOrder) {
|
|
961
1030
|
this.paymentMethodOrder = this.checkoutConfig.paymentMethodOrder;
|
|
962
1031
|
}
|
|
963
1032
|
const defaultSkinCheckoutOptions = await this.getDefaultSkinCheckoutOptions();
|
|
964
|
-
|
|
1033
|
+
if (!defaultSkinCheckoutOptions.cardElements ||
|
|
1034
|
+
!defaultSkinCheckoutOptions.paymentButtonElements) {
|
|
1035
|
+
throw new CheckoutError('Default skin must provide cardSelectors and paymentButtonSelectors');
|
|
1036
|
+
}
|
|
1037
|
+
cardElements =
|
|
1038
|
+
defaultSkinCheckoutOptions.cardElements;
|
|
1039
|
+
paymentButtonElements = defaultSkinCheckoutOptions.paymentButtonElements;
|
|
1040
|
+
checkoutOptions = this.getCheckoutOptions(defaultSkinCheckoutOptions);
|
|
1041
|
+
}
|
|
1042
|
+
else {
|
|
1043
|
+
cardElements = this.convertCardSelectorsToElements(this.checkoutConfig.cardSelectors, containerElement);
|
|
1044
|
+
paymentButtonElements = this.convertPaymentButtonSelectorsToElements(this.checkoutConfig.paymentButtonSelectors);
|
|
1045
|
+
checkoutOptions = this.getCheckoutOptions({});
|
|
965
1046
|
}
|
|
966
1047
|
if (this.checkoutConfig.paymentMethodOrder) {
|
|
967
1048
|
// eslint-disable-next-line no-console
|
|
968
1049
|
console.warn('paymentMethodOrder is using only for default skin and will be ignored if you are using custom checkout');
|
|
969
1050
|
}
|
|
970
|
-
await this.primerWrapper.renderCheckout(this.clientToken, checkoutOptions
|
|
1051
|
+
await this.primerWrapper.renderCheckout(this.clientToken, checkoutOptions, {
|
|
1052
|
+
container: containerElement,
|
|
1053
|
+
cardElements,
|
|
1054
|
+
paymentButtonElements,
|
|
1055
|
+
onSubmit: this.handleSubmit,
|
|
1056
|
+
onInputChange: this.handleInputChange,
|
|
1057
|
+
onMethodRender: this.handleMethodRender,
|
|
1058
|
+
});
|
|
971
1059
|
}
|
|
972
1060
|
async _processPaymentResult(result, primerHandler) {
|
|
973
1061
|
if (result.orderId) {
|
|
@@ -997,6 +1085,48 @@ class CheckoutInstance extends EventEmitter {
|
|
|
997
1085
|
throw new CheckoutError(`Unknown payment result type: ${result.type}`);
|
|
998
1086
|
}
|
|
999
1087
|
}
|
|
1088
|
+
getCheckoutOptions(options) {
|
|
1089
|
+
let wasPaymentProcessedStarted = false;
|
|
1090
|
+
return {
|
|
1091
|
+
...this.checkoutConfig,
|
|
1092
|
+
...options,
|
|
1093
|
+
onTokenizeSuccess: this.handleTokenizeSuccess,
|
|
1094
|
+
onResumeSuccess: this.handleResumeSuccess,
|
|
1095
|
+
onResumeError: error => {
|
|
1096
|
+
if (error.stack?.includes('PROCESSOR_3DS') &&
|
|
1097
|
+
error.code === 'RESUME_ERROR' &&
|
|
1098
|
+
error.message?.includes('fetch resume key')) {
|
|
1099
|
+
// Ignore 3DS close error, because it is not understandable by user
|
|
1100
|
+
return;
|
|
1101
|
+
}
|
|
1102
|
+
this.emit(EVENTS.PURCHASE_FAILURE, error);
|
|
1103
|
+
},
|
|
1104
|
+
onCheckoutFail: error => {
|
|
1105
|
+
this.emit(EVENTS.PURCHASE_FAILURE, error);
|
|
1106
|
+
},
|
|
1107
|
+
onTokenizeError: error => {
|
|
1108
|
+
this.emit(EVENTS.PURCHASE_FAILURE, error);
|
|
1109
|
+
},
|
|
1110
|
+
onTokenizeShouldStart: data => {
|
|
1111
|
+
this.emit(EVENTS.ERROR, undefined);
|
|
1112
|
+
this.emit(EVENTS.START_PURCHASE, data.paymentMethodType);
|
|
1113
|
+
return true;
|
|
1114
|
+
},
|
|
1115
|
+
onPaymentMethodAction: action => {
|
|
1116
|
+
switch (action) {
|
|
1117
|
+
case 'PAYMENT_METHOD_SELECTED':
|
|
1118
|
+
this.emit(EVENTS.ERROR, undefined);
|
|
1119
|
+
break;
|
|
1120
|
+
case 'PAYMENT_METHOD_UNSELECTED':
|
|
1121
|
+
if (!wasPaymentProcessedStarted) {
|
|
1122
|
+
this.emit(EVENTS.PURCHASE_CANCELLED);
|
|
1123
|
+
}
|
|
1124
|
+
wasPaymentProcessedStarted = false;
|
|
1125
|
+
break;
|
|
1126
|
+
}
|
|
1127
|
+
},
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1000
1130
|
async updatePrice(newPriceId) {
|
|
1001
1131
|
this._ensureNotDestroyed();
|
|
1002
1132
|
requireString(newPriceId, 'priceId');
|
|
@@ -1087,6 +1217,13 @@ class CheckoutInstance extends EventEmitter {
|
|
|
1087
1217
|
this.on(EVENTS.PURCHASE_COMPLETED, skin.onPurchaseCompleted);
|
|
1088
1218
|
return skin.getCheckoutOptions();
|
|
1089
1219
|
}
|
|
1220
|
+
async getCardDefaultSkinCheckoutOptions(node) {
|
|
1221
|
+
const CardSkin = (await import('./chunk-index.es2.js')).default;
|
|
1222
|
+
const skin = new CardSkin(node);
|
|
1223
|
+
skin.init();
|
|
1224
|
+
this.on(EVENTS.INPUT_ERROR, skin.onInputError);
|
|
1225
|
+
return skin.getCheckoutOptions();
|
|
1226
|
+
}
|
|
1090
1227
|
showInitializingLoader() {
|
|
1091
1228
|
renderLoader(this.checkoutConfig.container);
|
|
1092
1229
|
}
|
|
@@ -1121,19 +1258,14 @@ async function createCheckout(options) {
|
|
|
1121
1258
|
const primerWrapper = new PrimerWrapper();
|
|
1122
1259
|
primerWrapper.ensurePrimerAvailable();
|
|
1123
1260
|
const config = resolveConfig(options, 'createCheckout');
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
checkoutConfig
|
|
1128
|
-
}
|
|
1129
|
-
const checkout = new CheckoutInstance({
|
|
1130
|
-
...config,
|
|
1131
|
-
checkoutConfig: {
|
|
1132
|
-
...checkoutConfig,
|
|
1133
|
-
onInitialized,
|
|
1134
|
-
},
|
|
1135
|
-
});
|
|
1261
|
+
const checkout = new CheckoutInstance({
|
|
1262
|
+
...config,
|
|
1263
|
+
checkoutConfig: {
|
|
1264
|
+
...checkoutConfig,
|
|
1265
|
+
},
|
|
1136
1266
|
});
|
|
1267
|
+
await checkout.initialize();
|
|
1268
|
+
return checkout;
|
|
1137
1269
|
}
|
|
1138
1270
|
async function createClientSession(params) {
|
|
1139
1271
|
const { priceId, externalId, email, clientMetadata, countryCode } = params;
|
|
@@ -1154,6 +1286,54 @@ async function createClientSession(params) {
|
|
|
1154
1286
|
});
|
|
1155
1287
|
return apiClient.processSessionResponse(sessionResponse);
|
|
1156
1288
|
}
|
|
1289
|
+
async function initMethod(method, element, options) {
|
|
1290
|
+
const checkoutInstance = new CheckoutInstance({
|
|
1291
|
+
orgId: options.orgId,
|
|
1292
|
+
baseUrl: options.baseUrl,
|
|
1293
|
+
checkoutConfig: {
|
|
1294
|
+
priceId: options.priceId,
|
|
1295
|
+
customer: {
|
|
1296
|
+
externalId: options.externalId,
|
|
1297
|
+
email: options.email,
|
|
1298
|
+
},
|
|
1299
|
+
container: '',
|
|
1300
|
+
clientMetadata: options.meta,
|
|
1301
|
+
},
|
|
1302
|
+
});
|
|
1303
|
+
checkoutInstance._ensureNotDestroyed();
|
|
1304
|
+
if (!checkoutInstance.isReady()) {
|
|
1305
|
+
await checkoutInstance['createSession']();
|
|
1306
|
+
}
|
|
1307
|
+
checkoutInstance.on(EVENTS.METHOD_RENDER, options.onRenderSuccess);
|
|
1308
|
+
checkoutInstance.on(EVENTS.METHOD_RENDER_ERROR, options.onRenderError);
|
|
1309
|
+
checkoutInstance.on(EVENTS.LOADER_CHANGE, options.onLoaderChange);
|
|
1310
|
+
checkoutInstance.on(EVENTS.SUCCESS, options.onPaymentSuccess);
|
|
1311
|
+
checkoutInstance.on(EVENTS.PURCHASE_FAILURE, options.onPaymentFail);
|
|
1312
|
+
checkoutInstance.on(EVENTS.PURCHASE_CANCELLED, options.onPaymentCancel);
|
|
1313
|
+
checkoutInstance.on(EVENTS.ERROR, options.onErrorMessageChange);
|
|
1314
|
+
if (method === PaymentMethod.PAYMENT_CARD) {
|
|
1315
|
+
const cardDefaultOptions = await checkoutInstance['getCardDefaultSkinCheckoutOptions'](element);
|
|
1316
|
+
const checkoutOptions = checkoutInstance['getCheckoutOptions']({
|
|
1317
|
+
style: options.styles,
|
|
1318
|
+
...cardDefaultOptions,
|
|
1319
|
+
});
|
|
1320
|
+
await checkoutInstance.primerWrapper.initializeHeadlessCheckout(checkoutInstance.clientToken, checkoutOptions);
|
|
1321
|
+
return checkoutInstance.primerWrapper.initMethod(method, element, {
|
|
1322
|
+
cardElements: cardDefaultOptions.cardElements,
|
|
1323
|
+
onSubmit: checkoutInstance['handleSubmit'],
|
|
1324
|
+
onInputChange: checkoutInstance['handleInputChange'],
|
|
1325
|
+
onMethodRender: checkoutInstance['handleMethodRender'],
|
|
1326
|
+
onMethodRenderError: checkoutInstance['handleMethodRenderError'],
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
await checkoutInstance.primerWrapper.initializeHeadlessCheckout(checkoutInstance.clientToken, checkoutInstance['getCheckoutOptions']({
|
|
1330
|
+
style: options.styles,
|
|
1331
|
+
}));
|
|
1332
|
+
return checkoutInstance.primerWrapper.initMethod(method, element, {
|
|
1333
|
+
onMethodRender: checkoutInstance['handleMethodRender'],
|
|
1334
|
+
onMethodRenderError: checkoutInstance['handleMethodRenderError'],
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1157
1337
|
|
|
1158
1338
|
/**
|
|
1159
1339
|
* @fileoverview Main entry point for @funnelfox/billing
|
|
@@ -1162,6 +1342,7 @@ const Billing = {
|
|
|
1162
1342
|
configure: configure,
|
|
1163
1343
|
createCheckout: createCheckout,
|
|
1164
1344
|
createClientSession: createClientSession,
|
|
1345
|
+
initMethod: initMethod,
|
|
1165
1346
|
};
|
|
1166
1347
|
if (typeof window !== 'undefined') {
|
|
1167
1348
|
window.Billing = Billing;
|