@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
|
@@ -217,7 +217,7 @@ exports.PaymentMethod = void 0;
|
|
|
217
217
|
/**
|
|
218
218
|
* @fileoverview Constants for Funnefox SDK
|
|
219
219
|
*/
|
|
220
|
-
const SDK_VERSION = '0.
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
...
|
|
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
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
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
|
-
|
|
493
|
-
|
|
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
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
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.
|
|
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
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
checkoutConfig
|
|
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;
|