@rebilly/instruments 3.12.3-beta.0 → 3.13.2-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.
- package/README.md +1 -1
- package/dist/index.js +43 -66
- package/dist/index.min.js +43 -66
- package/package.json +3 -6
- package/src/functions/destroy.js +8 -2
- package/src/functions/mount/fetch-data.js +9 -2
- package/src/functions/mount/index.js +15 -10
- package/src/functions/mount/mount.spec.js +10 -11
- package/src/functions/mount/setup-framepay-theme.js +30 -72
- package/src/functions/mount/setup-options.js +2 -2
- package/src/functions/mount/{setup-styles.js → setup-styles-vars.js} +9 -7
- package/src/functions/purchase.js +2 -5
- package/src/functions/setup.js +3 -6
- package/src/functions/show.js +2 -2
- package/src/functions/show.spec.js +4 -4
- package/src/functions/update.spec.js +4 -3
- package/src/instance.js +4 -1
- package/src/loader/index.js +57 -33
- package/src/storefront/index.js +2 -5
- package/src/storefront/payment-instruments.js +7 -0
- package/src/style/base/__snapshots__/theme.spec.js.snap +136 -220
- package/src/style/base/default-theme.js +187 -14
- package/src/style/base/index.js +487 -79
- package/src/style/base/theme.js +3 -4
- package/src/style/base/theme.spec.js +2 -3
- package/src/style/index.js +4 -24
- package/src/style/utils/color-values.js +1 -1
- package/src/style/utils/minifyCss.js +14 -0
- package/src/views/common/iframe/base-iframe.js +3 -2
- package/src/views/common/iframe/event-listeners.js +12 -9
- package/src/views/common/iframe/method-iframe.js +3 -1
- package/src/views/common/iframe/modal-iframe.js +4 -2
- package/src/views/common/iframe/view-iframe.js +3 -1
- package/src/views/confirmation.js +12 -7
- package/src/views/errors.js +95 -0
- package/src/views/method-selector/express-methods.js +51 -0
- package/src/views/method-selector/generate-framepay-config.js +54 -0
- package/src/views/method-selector/generate-framepay-config.spec.js +195 -0
- package/src/views/method-selector/get-payment-methods.js +0 -1
- package/src/views/method-selector/index.js +45 -58
- package/src/views/method-selector/method-selector.spec.js +1 -1
- package/src/views/method-selector/mount-express-methods.js +66 -26
- package/src/views/modal.js +1 -1
- package/src/views/result.js +3 -3
- package/src/views/summary.js +24 -190
- package/tests/mocks/storefront-api-mock.js +48 -27
- package/src/style/browserslist.js +0 -1
- package/src/style/components/accordion.js +0 -140
- package/src/style/components/address.js +0 -55
- package/src/style/components/button.js +0 -117
- package/src/style/components/divider.js +0 -39
- package/src/style/components/forms/checkbox.js +0 -75
- package/src/style/components/forms/field.js +0 -56
- package/src/style/components/forms/form.js +0 -18
- package/src/style/components/forms/input.js +0 -77
- package/src/style/components/forms/label.js +0 -55
- package/src/style/components/forms/radio.js +0 -80
- package/src/style/components/forms/select.js +0 -86
- package/src/style/components/forms/validation.js +0 -72
- package/src/style/components/icons.js +0 -13
- package/src/style/components/index.js +0 -39
- package/src/style/components/loader.js +0 -41
- package/src/style/components/methods.js +0 -97
- package/src/style/components/overlay.js +0 -24
- package/src/style/helpers/index.js +0 -54
- package/src/style/payment-instruments/content.js +0 -8
- package/src/style/payment-instruments/index.js +0 -14
- package/src/style/payment-instruments/payment-card.js +0 -27
- package/src/style/payment-instruments/payment-instrument-list.js +0 -44
- package/src/style/payment-instruments/payment-instrument.js +0 -55
- package/src/style/utils/remove-empty-null.js +0 -10
- package/src/style/vendor/framepay.js +0 -28
- package/src/style/vendor/postmate.js +0 -18
- package/src/style/views/confirmation.js +0 -26
- package/src/style/views/index.js +0 -16
- package/src/style/views/method-selector.js +0 -11
- package/src/style/views/modal.js +0 -91
- package/src/style/views/result.js +0 -52
- package/src/style/views/summary.js +0 -118
- package/src/views/__snapshots__/summary.spec.js.snap +0 -246
- package/src/views/method-selector/express-methods/apple-pay.js +0 -92
- package/src/views/method-selector/express-methods/index.js +0 -25
- package/src/views/method-selector/mount-methods.js +0 -178
- package/src/views/summary.spec.js +0 -145
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import camelCase from 'lodash.camelcase';
|
|
2
2
|
import Events from '../../../events';
|
|
3
|
+
import { showError } from '../../errors';
|
|
3
4
|
|
|
4
5
|
export function dispatchRebillyInsturmentEventHandler(iframe) {
|
|
5
6
|
iframe.component.on(`${iframe.name}-dispatch`, ({ event, detail }) => {
|
|
@@ -13,15 +14,13 @@ export function resizeComponentHandler(iframe) {
|
|
|
13
14
|
});
|
|
14
15
|
}
|
|
15
16
|
|
|
16
|
-
export function stopLoaderHandler(iframe, data
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
iframe.component.on(`${iframe.name}-stop-loading`, (id = null) => {
|
|
24
|
-
data.loader?.stopLoading({ section: data.section, id: id || data.id });
|
|
17
|
+
export function stopLoaderHandler(iframe, data) {
|
|
18
|
+
iframe.component.on(`${iframe.name}-stop-loading`, (id) => {
|
|
19
|
+
let {section} = data;
|
|
20
|
+
if (!section) {
|
|
21
|
+
section = id.includes('summary') ? 'summary' : 'form';
|
|
22
|
+
}
|
|
23
|
+
data.loader?.stopLoading({ section, id });
|
|
25
24
|
});
|
|
26
25
|
}
|
|
27
26
|
|
|
@@ -41,3 +40,7 @@ export function displayOverlay(iframe) {
|
|
|
41
40
|
}
|
|
42
41
|
});
|
|
43
42
|
}
|
|
43
|
+
|
|
44
|
+
export function showErrorHandler(iframe) {
|
|
45
|
+
iframe.component.on(`${iframe.name}-show-error`, showError);
|
|
46
|
+
}
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
dispatchRebillyInsturmentEventHandler,
|
|
4
4
|
resizeComponentHandler,
|
|
5
5
|
stopLoaderHandler,
|
|
6
|
-
displayOverlay
|
|
6
|
+
displayOverlay,
|
|
7
|
+
showErrorHandler
|
|
7
8
|
} from './event-listeners';
|
|
8
9
|
|
|
9
10
|
export class MethodIframe extends BaseIframe {
|
|
@@ -19,5 +20,6 @@ export class MethodIframe extends BaseIframe {
|
|
|
19
20
|
id
|
|
20
21
|
});
|
|
21
22
|
displayOverlay(this);
|
|
23
|
+
showErrorHandler(this);
|
|
22
24
|
}
|
|
23
25
|
}
|
|
@@ -3,7 +3,8 @@ import {
|
|
|
3
3
|
dispatchRebillyInsturmentEventHandler,
|
|
4
4
|
resizeComponentHandler,
|
|
5
5
|
changeIframeSrcHandler,
|
|
6
|
-
stopLoaderHandler
|
|
6
|
+
stopLoaderHandler,
|
|
7
|
+
showErrorHandler
|
|
7
8
|
} from './event-listeners';
|
|
8
9
|
|
|
9
10
|
export class ModalIframe extends BaseIframe {
|
|
@@ -18,8 +19,9 @@ export class ModalIframe extends BaseIframe {
|
|
|
18
19
|
stopLoaderHandler(this, {
|
|
19
20
|
loader,
|
|
20
21
|
section: 'modal',
|
|
21
|
-
id:
|
|
22
|
+
id: this.name
|
|
22
23
|
});
|
|
24
|
+
showErrorHandler(this);
|
|
23
25
|
|
|
24
26
|
// Close modal via postmate
|
|
25
27
|
this.component.on(`${this.name}-close`, (...args) => {
|
|
@@ -2,7 +2,8 @@ import BaseIframe from './base-iframe';
|
|
|
2
2
|
import {
|
|
3
3
|
dispatchRebillyInsturmentEventHandler,
|
|
4
4
|
resizeComponentHandler,
|
|
5
|
-
stopLoaderHandler
|
|
5
|
+
stopLoaderHandler,
|
|
6
|
+
showErrorHandler,
|
|
6
7
|
} from './event-listeners';
|
|
7
8
|
|
|
8
9
|
export class ViewIframe extends BaseIframe {
|
|
@@ -14,5 +15,6 @@ export class ViewIframe extends BaseIframe {
|
|
|
14
15
|
dispatchRebillyInsturmentEventHandler(this);
|
|
15
16
|
resizeComponentHandler(this);
|
|
16
17
|
stopLoaderHandler(this, { loader });
|
|
18
|
+
showErrorHandler(this);
|
|
17
19
|
}
|
|
18
20
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { purchase } from '../functions/purchase';
|
|
2
2
|
import { setup } from '../functions/setup';
|
|
3
3
|
import { ViewIframe } from './common/iframe';
|
|
4
|
-
import { replaceContent } from './common/render-utilities';
|
|
5
4
|
import { updateMethodSelector } from './method-selector';
|
|
6
5
|
import { updateSummary } from './summary';
|
|
7
6
|
|
|
@@ -16,9 +15,14 @@ export async function mountConfirmation({ payload: instrument, state }) {
|
|
|
16
15
|
updateSummary({ state, instrument });
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
const contentElement = state.form.querySelector('.rebilly-instruments-content');
|
|
19
|
+
contentElement.insertAdjacentHTML('afterend', baseConfirmationHTML);
|
|
20
20
|
|
|
21
|
-
state.
|
|
21
|
+
const methodSelectorElement = state.form.querySelector('.rebilly-instruments-method-selector');
|
|
22
|
+
methodSelectorElement.style.visibility = 'hidden';
|
|
23
|
+
methodSelectorElement.style.height = '0px';
|
|
24
|
+
|
|
25
|
+
state.loader.startLoading({ id: 'rebilly-instruments-confirmation' });
|
|
22
26
|
|
|
23
27
|
const container = document.querySelector('.rebilly-instruments-confirmation');
|
|
24
28
|
|
|
@@ -27,7 +31,7 @@ export async function mountConfirmation({ payload: instrument, state }) {
|
|
|
27
31
|
const model = {
|
|
28
32
|
options: state.options,
|
|
29
33
|
data: state.data.toPostmatesModel(),
|
|
30
|
-
|
|
34
|
+
mainStyleVars: state.mainStyleVars,
|
|
31
35
|
instrument
|
|
32
36
|
};
|
|
33
37
|
const name = 'rebilly-instruments-confirmation';
|
|
@@ -50,7 +54,7 @@ export async function mountConfirmation({ payload: instrument, state }) {
|
|
|
50
54
|
});
|
|
51
55
|
|
|
52
56
|
iframe.component.on('choose-another-method', () => {
|
|
53
|
-
state.iframeComponents = state.iframeComponents.filter((item) => {
|
|
57
|
+
state.iframeComponents.form = state.iframeComponents.form.filter((item) => {
|
|
54
58
|
if (item.name === iframe.name) {
|
|
55
59
|
item.destroy();
|
|
56
60
|
return false;
|
|
@@ -60,8 +64,9 @@ export async function mountConfirmation({ payload: instrument, state }) {
|
|
|
60
64
|
if (state.data.isPurchase) {
|
|
61
65
|
updateSummary({ state });
|
|
62
66
|
}
|
|
63
|
-
updateMethodSelector({ state,
|
|
67
|
+
updateMethodSelector({ state, mainStyleVars: state.mainStyleVars });
|
|
68
|
+
state.form.querySelector('.rebilly-instruments-confirmation').remove();
|
|
64
69
|
});
|
|
65
70
|
|
|
66
|
-
state.iframeComponents.push(iframe);
|
|
71
|
+
state.iframeComponents.form.push(iframe);
|
|
67
72
|
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const errorTemplate = (error) => {
|
|
2
|
+
const title = 'Error';
|
|
3
|
+
|
|
4
|
+
function displayString(message = null) {
|
|
5
|
+
if (message === null) {
|
|
6
|
+
message = 'An unexpected error occurred';
|
|
7
|
+
|
|
8
|
+
if (typeof error === 'string') {
|
|
9
|
+
message = error;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
if (error.error) {
|
|
13
|
+
message = error.error;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (error.message) {
|
|
17
|
+
message = error.message;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return `<p class="rebilly-instruments-error-card-message">${message}</p>`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function displayList() {
|
|
25
|
+
function displayDetail(detail) {
|
|
26
|
+
let detailMessage = detail;
|
|
27
|
+
if (detail['data-rebilly']) {
|
|
28
|
+
detailMessage = `"${detail['data-rebilly']}" ${detail.error}`
|
|
29
|
+
}
|
|
30
|
+
return detailMessage;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (error.details.length > 1) {
|
|
34
|
+
return `<ul class="rebilly-instruments-error-card-details">
|
|
35
|
+
${error.details.map(detail => `<li>${displayDetail(detail)}</li>`).join('')}
|
|
36
|
+
</ul>`
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return displayString(displayDetail(error.details[0]));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return `<div class="rebilly-instruments-error-card">
|
|
43
|
+
<header class="rebilly-instruments-error-card-header">
|
|
44
|
+
<p class="rebilly-instruments-error-card-title">${title}</p>
|
|
45
|
+
<button class="rebilly-instruments-error-card-close-button">
|
|
46
|
+
<svg class="rebilly-instruments-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
47
|
+
<path d="M12 10.5858l2.8284-2.8284c.3906-.3906 1.0237-.3906 1.4142 0 .3906.3905.3906 1.0236 0 1.4142L13.4142 12l2.8284 2.8284c.3906.3906.3906 1.0237 0 1.4142-.3905.3906-1.0236.3906-1.4142 0L12 13.4142l-2.8284 2.8284c-.3906.3906-1.0237.3906-1.4142 0-.3906-.3905-.3906-1.0236 0-1.4142L10.5858 12 7.7574 9.1716c-.3906-.3906-.3906-1.0237 0-1.4142.3905-.3906 1.0236-.3906 1.4142 0L12 10.5858z" fill-rule="nonzero"/>
|
|
48
|
+
</svg>
|
|
49
|
+
</button>
|
|
50
|
+
</header>
|
|
51
|
+
${error.details ? displayList() : displayString()}
|
|
52
|
+
</div>`
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export function clearError() {
|
|
56
|
+
const errorContainer = document.querySelector('#rebilly-instruments-error');
|
|
57
|
+
if (!errorContainer) return ;
|
|
58
|
+
|
|
59
|
+
errorContainer.innerHTML = '';
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function showError(error) {
|
|
63
|
+
const errorContainer = document.querySelector('#rebilly-instruments-error');
|
|
64
|
+
if (!errorContainer) return ;
|
|
65
|
+
|
|
66
|
+
errorContainer.innerHTML = errorTemplate(error);
|
|
67
|
+
|
|
68
|
+
const closeButton = document.querySelector('.rebilly-instruments-error-card-close-button');
|
|
69
|
+
closeButton.addEventListener('click', clearError);
|
|
70
|
+
|
|
71
|
+
function clickOutsideError(e) {
|
|
72
|
+
if (errorContainer.contains(e.target)) return;
|
|
73
|
+
|
|
74
|
+
window.removeEventListener('click', clickOutsideError, false);
|
|
75
|
+
clearError();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function windowBlur() {
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
if (document.activeElement.tagName === 'IFRAME') {
|
|
81
|
+
window.removeEventListener('click', windowBlur, false);
|
|
82
|
+
clearError();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
window.addEventListener('click', clickOutsideError);
|
|
88
|
+
window.addEventListener('blur', windowBlur, { once: true });
|
|
89
|
+
|
|
90
|
+
errorContainer.scrollIntoView({behavior: 'smooth', block: 'end', inline: 'nearest'});
|
|
91
|
+
console.error('Rebilly Instruments Error', error);
|
|
92
|
+
|
|
93
|
+
// Must focus to ensure window blur event will trigger
|
|
94
|
+
window.focus();
|
|
95
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export default function mountExpressMethod({
|
|
2
|
+
state,
|
|
3
|
+
id
|
|
4
|
+
}) {
|
|
5
|
+
const {Rebilly} = window;
|
|
6
|
+
const container = document.querySelector(`.rebilly-instruments-${id}-method`);
|
|
7
|
+
|
|
8
|
+
// Hack: The correct way to do this is to accept the options via the framepay package
|
|
9
|
+
// Will remove once these options are added to framepay
|
|
10
|
+
function updateApplePayStyling() {
|
|
11
|
+
const applePayButton = document.querySelector('#rebilly-apple-pay-button');
|
|
12
|
+
const {
|
|
13
|
+
applePayDisplayOptions: {
|
|
14
|
+
buttonHeight
|
|
15
|
+
}
|
|
16
|
+
} = state.options.digitalWallet.applePay;
|
|
17
|
+
|
|
18
|
+
applePayButton.style.margin = '0px';
|
|
19
|
+
applePayButton.style.width = '100%';
|
|
20
|
+
applePayButton.style.height = buttonHeight;
|
|
21
|
+
applePayButton.style.cursor = 'pointer';
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function mountButton() {
|
|
25
|
+
if(!container.children.length) {
|
|
26
|
+
const rebillyMountFunction = {
|
|
27
|
+
'google-pay': 'googlePay',
|
|
28
|
+
'pay-pal-billing-agreement': 'paypal',
|
|
29
|
+
'apple-pay': 'applePay'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (rebillyMountFunction[id]) {
|
|
33
|
+
Rebilly[rebillyMountFunction[id]].mount(`.rebilly-instruments-${id}-method`);
|
|
34
|
+
|
|
35
|
+
if (id === 'apple-pay') {
|
|
36
|
+
updateApplePayStyling();
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
console.warn(`method '${id}' is not supported`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Rebilly?.on('ready', () => {
|
|
45
|
+
mountButton();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
Rebilly?.on('error', error => {
|
|
49
|
+
console.error(error)
|
|
50
|
+
});
|
|
51
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import merge from 'lodash.merge';
|
|
2
|
+
|
|
3
|
+
export function generateFramepayConfig ({
|
|
4
|
+
state,
|
|
5
|
+
methodIds
|
|
6
|
+
} = {}) {
|
|
7
|
+
const {
|
|
8
|
+
options,
|
|
9
|
+
data
|
|
10
|
+
} = state;
|
|
11
|
+
|
|
12
|
+
const config = {
|
|
13
|
+
style: options.themeFramepay,
|
|
14
|
+
locale: options?.locale || 'auto',
|
|
15
|
+
organizationId: options.organizationId,
|
|
16
|
+
websiteId: options.websiteId,
|
|
17
|
+
methods: data.readyToPay,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
if (methodIds.includes('pay-pal-billing-agreement')) {
|
|
21
|
+
config.transactionData = merge(
|
|
22
|
+
typeof config.transactionData === 'object' ? config.transactionData : {},
|
|
23
|
+
data.amountAndCurrency
|
|
24
|
+
);
|
|
25
|
+
config.paypal = options.paymentInstruments.paypal;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (methodIds.includes('google-pay')) {
|
|
29
|
+
config.transactionData = merge(
|
|
30
|
+
typeof config.transactionData === 'object' ? config.transactionData : {},
|
|
31
|
+
options.digitalWallet.googlePay?.transactionData
|
|
32
|
+
);
|
|
33
|
+
config.googlePay = options.digitalWallet.googlePay.googlePayDisplayOptions;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (methodIds.includes('apple-pay')) {
|
|
37
|
+
config.transactionData = merge(
|
|
38
|
+
typeof config.transactionData === 'object' ? config.transactionData : {},
|
|
39
|
+
options.digitalWallet.applePay?.transactionData
|
|
40
|
+
);
|
|
41
|
+
config.applePay = options.digitalWallet.applePay.applePayDisplayOptions;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (options.publishableKey) {
|
|
45
|
+
config.publishableKey = options.publishableKey;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (options.jwt) {
|
|
49
|
+
config.jwt = options.jwt;
|
|
50
|
+
config.sandbox = options.apiMode === 'sandbox';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return config;
|
|
54
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import {generateFramepayConfig} from './generate-framepay-config';
|
|
2
|
+
|
|
3
|
+
describe('Generate FramePay Config', () => {
|
|
4
|
+
let state;
|
|
5
|
+
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
state = {
|
|
8
|
+
options: {
|
|
9
|
+
themeFramepay: {},
|
|
10
|
+
locale: 'en-CA',
|
|
11
|
+
organizationId: 'test-organization-id',
|
|
12
|
+
websiteId: 'test-website-id'
|
|
13
|
+
},
|
|
14
|
+
data: {
|
|
15
|
+
readyToPay: []
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should generate default config', () => {
|
|
21
|
+
const config = generateFramepayConfig({
|
|
22
|
+
state,
|
|
23
|
+
methodIds: []
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const {options, data} = state;
|
|
27
|
+
|
|
28
|
+
expect(config).toEqual(expect.objectContaining ({
|
|
29
|
+
style: options.themeFramepay,
|
|
30
|
+
locale: options.locale,
|
|
31
|
+
organizationId: options.organizationId,
|
|
32
|
+
websiteId: options.websiteId,
|
|
33
|
+
methods: data.readyToPay,
|
|
34
|
+
}))
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should add publishableKey', () => {
|
|
38
|
+
state.options.publishableKey = 'test-publishable-key';
|
|
39
|
+
|
|
40
|
+
const config = generateFramepayConfig({
|
|
41
|
+
state,
|
|
42
|
+
methodIds: []
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
expect(config).toEqual(expect.objectContaining ({
|
|
46
|
+
publishableKey: state.options.publishableKey
|
|
47
|
+
}));
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should add jwt', () => {
|
|
51
|
+
state.options.jwt = 'test-jwt';
|
|
52
|
+
state.options.apiMode = 'sandbox';
|
|
53
|
+
|
|
54
|
+
const config = generateFramepayConfig({
|
|
55
|
+
state,
|
|
56
|
+
methodIds: []
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
expect(config).toEqual(expect.objectContaining ({
|
|
60
|
+
jwt: state.options.jwt,
|
|
61
|
+
sandbox: true
|
|
62
|
+
}));
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should add configurations for PayPal', () => {
|
|
66
|
+
state.data.amountAndCurrency = {
|
|
67
|
+
amount: 10,
|
|
68
|
+
currency: 'CAD'
|
|
69
|
+
};
|
|
70
|
+
state.options.paymentInstruments = {
|
|
71
|
+
paypal: {
|
|
72
|
+
test: 'key'
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const config = generateFramepayConfig({
|
|
77
|
+
state,
|
|
78
|
+
methodIds: ['pay-pal-billing-agreement']
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
expect(config).toEqual(expect.objectContaining ({
|
|
82
|
+
transactionData: expect.objectContaining(
|
|
83
|
+
state.data.amountAndCurrency
|
|
84
|
+
),
|
|
85
|
+
paypal: state.options.paymentInstruments.paypal
|
|
86
|
+
}));
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should add configurations for Google Pay', () => {
|
|
90
|
+
state.options.digitalWallet = {
|
|
91
|
+
googlePay: {
|
|
92
|
+
transactionData: {
|
|
93
|
+
test: 'key'
|
|
94
|
+
},
|
|
95
|
+
googlePayDisplayOptions: {
|
|
96
|
+
test: 'key'
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const config = generateFramepayConfig({
|
|
102
|
+
state,
|
|
103
|
+
methodIds: ['google-pay']
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
expect(config).toEqual(expect.objectContaining ({
|
|
107
|
+
transactionData: expect.objectContaining(
|
|
108
|
+
state.options.digitalWallet.googlePay.transactionData
|
|
109
|
+
),
|
|
110
|
+
googlePay: state.options.digitalWallet.googlePay.googlePayDisplayOptions
|
|
111
|
+
}));
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should add configurations for Apple Pay', () => {
|
|
115
|
+
state.options.digitalWallet = {
|
|
116
|
+
applePay: {
|
|
117
|
+
transactionData: {
|
|
118
|
+
test: 'key'
|
|
119
|
+
},
|
|
120
|
+
applePayDisplayOptions: {
|
|
121
|
+
test: 'key'
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const config = generateFramepayConfig({
|
|
127
|
+
state,
|
|
128
|
+
methodIds: ['apple-pay']
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
expect(config).toEqual(expect.objectContaining ({
|
|
132
|
+
transactionData: expect.objectContaining(
|
|
133
|
+
state.options.digitalWallet.applePay.transactionData
|
|
134
|
+
),
|
|
135
|
+
applePay: state.options.digitalWallet.applePay.applePayDisplayOptions
|
|
136
|
+
}));
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should add all instrument methods together', () => {
|
|
140
|
+
state.data.amountAndCurrency = {
|
|
141
|
+
test: 'key'
|
|
142
|
+
};
|
|
143
|
+
state.options = {
|
|
144
|
+
paymentInstruments: {
|
|
145
|
+
paypal: {
|
|
146
|
+
test: 'key'
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
digitalWallet: {
|
|
150
|
+
googlePay: {
|
|
151
|
+
transactionData: {
|
|
152
|
+
test: 'key'
|
|
153
|
+
},
|
|
154
|
+
googlePayDisplayOptions: {
|
|
155
|
+
test: 'key'
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
applePay: {
|
|
159
|
+
transactionData: {
|
|
160
|
+
test: 'key'
|
|
161
|
+
},
|
|
162
|
+
applePayDisplayOptions: {
|
|
163
|
+
test: 'key'
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const config = generateFramepayConfig({
|
|
170
|
+
state,
|
|
171
|
+
methodIds: ['pay-pal-billing-agreement', 'google-pay', 'apple-pay']
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
expect(config).toEqual(expect.objectContaining ({
|
|
175
|
+
transactionData: expect.objectContaining(
|
|
176
|
+
state.data.amountAndCurrency
|
|
177
|
+
),
|
|
178
|
+
paypal: state.options.paymentInstruments.paypal
|
|
179
|
+
}));
|
|
180
|
+
|
|
181
|
+
expect(config).toEqual(expect.objectContaining ({
|
|
182
|
+
transactionData: expect.objectContaining(
|
|
183
|
+
state.options.digitalWallet.googlePay.transactionData
|
|
184
|
+
),
|
|
185
|
+
googlePay: state.options.digitalWallet.googlePay.googlePayDisplayOptions
|
|
186
|
+
}));
|
|
187
|
+
|
|
188
|
+
expect(config).toEqual(expect.objectContaining ({
|
|
189
|
+
transactionData: expect.objectContaining(
|
|
190
|
+
state.options.digitalWallet.applePay.transactionData
|
|
191
|
+
),
|
|
192
|
+
applePay: state.options.digitalWallet.applePay.applePayDisplayOptions
|
|
193
|
+
}));
|
|
194
|
+
});
|
|
195
|
+
});
|
|
@@ -9,7 +9,6 @@ const isExpressMethod = ({ method, feature }) => (
|
|
|
9
9
|
|
|
10
10
|
const isSupportedMethod = ({ method }) => SUPPORTED_METHODS.includes(method);
|
|
11
11
|
|
|
12
|
-
// TODO: just loader is used. We could simplify signature
|
|
13
12
|
export function getPaymentMethods({ state }) {
|
|
14
13
|
const result = {
|
|
15
14
|
EXPRESS_METHODS: [],
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
/* eslint-disable no-undef */
|
|
2
2
|
import { collectData } from '@rebilly/risk-data-collector';
|
|
3
3
|
import { getPaymentMethods } from './get-payment-methods';
|
|
4
|
+
import { fetchData } from '../../functions/mount/fetch-data';
|
|
5
|
+
import { ViewIframe } from '../common/iframe';
|
|
4
6
|
import { mountExpressMethods } from './mount-express-methods';
|
|
5
7
|
import { generateDigitalWallet } from './generate-digital-wallet';
|
|
6
|
-
import { MountMethods } from './mount-methods';
|
|
7
|
-
import { fetchData } from '../../functions/mount/fetch-data';
|
|
8
8
|
|
|
9
9
|
export const baseMethodSelectorHTML = (compactExpressInstruments) => `
|
|
10
10
|
<div class="rebilly-instruments-content">
|
|
11
|
+
<div id="rebilly-instruments-error"></div>
|
|
11
12
|
<div class="rebilly-instruments-method-selector ${compactExpressInstruments ? 'has-express-compact' : ''}">
|
|
12
13
|
<div class="rebilly-instruments-express-methods ${
|
|
13
14
|
compactExpressInstruments ? 'is-compact' : ''
|
|
@@ -23,81 +24,67 @@ export const baseMethodSelectorHTML = (compactExpressInstruments) => `
|
|
|
23
24
|
</div>
|
|
24
25
|
`;
|
|
25
26
|
|
|
26
|
-
export function mountMethodSelector({ state }) {
|
|
27
|
+
export async function mountMethodSelector({ state }) {
|
|
27
28
|
const { EXPRESS_METHODS, METHODS } = getPaymentMethods({ state });
|
|
28
29
|
|
|
29
|
-
state.form.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
);
|
|
39
|
-
METHODS_DIVIDER.style.display =
|
|
40
|
-
METHODS.length && EXPRESS_METHODS.length ? 'block' : 'none';
|
|
41
|
-
const METHODS_CONTAINER = document.querySelector(
|
|
42
|
-
'.rebilly-instruments-methods'
|
|
43
|
-
);
|
|
30
|
+
const methodSelectorElement = state.form.querySelector('.rebilly-instruments-method-selector');
|
|
31
|
+
if (methodSelectorElement) {
|
|
32
|
+
methodSelectorElement.style.visibility = 'visible';
|
|
33
|
+
methodSelectorElement.style.height = 'auto';
|
|
34
|
+
} else {
|
|
35
|
+
state.form.innerHTML += baseMethodSelectorHTML(
|
|
36
|
+
state.options.paymentInstruments.compactExpressInstruments && EXPRESS_METHODS.length
|
|
37
|
+
);
|
|
38
|
+
}
|
|
44
39
|
|
|
45
|
-
|
|
40
|
+
const METHODS_CONTAINER = document.querySelector('.rebilly-instruments-methods');
|
|
41
|
+
const EXPRESS_METHODS_CONTAINER = document.querySelector('.rebilly-instruments-express-methods-container');
|
|
46
42
|
|
|
47
|
-
if
|
|
48
|
-
|
|
49
|
-
state,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
43
|
+
if(EXPRESS_METHODS.length) {
|
|
44
|
+
if (!methodSelectorElement) {
|
|
45
|
+
state.options.digitalWallet = generateDigitalWallet({state, EXPRESS_METHODS});
|
|
46
|
+
mountExpressMethods({
|
|
47
|
+
state,
|
|
48
|
+
methods: EXPRESS_METHODS,
|
|
49
|
+
container: EXPRESS_METHODS_CONTAINER,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
53
52
|
} else {
|
|
54
|
-
|
|
53
|
+
EXPRESS_METHODS_CONTAINER.style.display = 'none';
|
|
54
|
+
document.querySelector('.rebilly-instruments-divider')
|
|
55
|
+
.style.display = 'none';
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
if (
|
|
58
|
-
|
|
59
|
-
state,
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
if (METHODS.length) {
|
|
59
|
+
const model = {
|
|
60
|
+
options: state.options,
|
|
61
|
+
data: state.data.toPostmatesModel(),
|
|
62
|
+
mainStyleVars: state.mainStyleVars,
|
|
63
|
+
};
|
|
64
|
+
const { paymentMethodsUrl } = state.options._computed;
|
|
65
|
+
|
|
66
|
+
const iframe = await new ViewIframe({
|
|
67
|
+
name: 'rebilly-instruments-methods',
|
|
68
|
+
url: `${paymentMethodsUrl}`,
|
|
69
|
+
container: METHODS_CONTAINER,
|
|
70
|
+
model
|
|
62
71
|
});
|
|
72
|
+
iframe.bindEventListeners({loader: state.loader});
|
|
73
|
+
state.iframeComponents.form.push(iframe);
|
|
63
74
|
} else {
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (!METHODS.length && !EXPRESS_METHODS.length) {
|
|
68
|
-
state.form.innerHTML = `
|
|
69
|
-
<p data-rebilly-i18n="form.error.noPaymentMethods">
|
|
70
|
-
No payment methods available for this transaction, please contact support.
|
|
71
|
-
<p>
|
|
72
|
-
`;
|
|
73
|
-
state.form.style.minHeight = 'auto';
|
|
75
|
+
METHODS_CONTAINER.style.display = 'none';
|
|
74
76
|
}
|
|
75
|
-
|
|
76
|
-
state.translate.translateItems();
|
|
77
|
-
|
|
78
|
-
state.loader.stopLoading({ id: 'initForm' });
|
|
79
77
|
}
|
|
80
78
|
|
|
81
79
|
export async function updateMethodSelector({ state }) {
|
|
82
|
-
state.loader.startLoading({ id: '
|
|
83
|
-
const { riskMetadata } = await collectData();
|
|
80
|
+
state.loader.startLoading({ id: 'rebilly-instruments-methods' });
|
|
84
81
|
|
|
82
|
+
const { riskMetadata } = await collectData();
|
|
85
83
|
state.data = await fetchData({ state, riskMetadata });
|
|
86
84
|
|
|
87
85
|
if (state.data.transaction && state.data.transaction?.type === 'setup') {
|
|
88
86
|
state.options.transactionType = 'setup';
|
|
89
87
|
}
|
|
90
88
|
|
|
91
|
-
state.form
|
|
92
|
-
.querySelectorAll(':not(.rebilly-instruments-confirmation)')
|
|
93
|
-
.forEach((element) => {
|
|
94
|
-
if (
|
|
95
|
-
!element.classList.contains('rebilly-instruments-loader') &&
|
|
96
|
-
!element.classList.contains('rebilly-instruments-loader-spinner')
|
|
97
|
-
) {
|
|
98
|
-
element.remove();
|
|
99
|
-
}
|
|
100
|
-
});
|
|
101
|
-
|
|
102
89
|
mountMethodSelector({ state });
|
|
103
90
|
}
|