@rebilly/instruments 3.2.1-beta.0 → 3.4.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/index.js +13 -13
  2. package/dist/index.min.js +13 -13
  3. package/package.json +1 -1
  4. package/src/functions/mount/index.js +5 -3
  5. package/src/functions/mount/mount.spec.js +5 -7
  6. package/src/functions/mount/setup-framepay-theme.js +44 -21
  7. package/src/functions/mount/setup-framepay.js +17 -38
  8. package/src/functions/mount/setup-options.js +6 -1
  9. package/src/functions/mount/setup-options.spec.js +1 -2
  10. package/src/functions/purchase.js +13 -4
  11. package/src/functions/setup.js +20 -2
  12. package/src/i18n/en.json +3 -1
  13. package/src/i18n/es.json +3 -1
  14. package/src/instance.spec.js +4 -2
  15. package/src/storefront/index.js +11 -9
  16. package/src/storefront/invoices.js +1 -1
  17. package/src/storefront/models/payment-metadata.js +7 -0
  18. package/src/storefront/models/ready-to-pay-model.js +6 -1
  19. package/src/storefront/payment-instruments.js +2 -2
  20. package/src/storefront/ready-to-pay.js +19 -5
  21. package/src/storefront/transactions.js +1 -1
  22. package/src/style/components/accordion.js +127 -0
  23. package/src/style/components/button.js +20 -0
  24. package/src/style/components/forms/checkbox.js +17 -19
  25. package/src/style/components/forms/form.js +1 -2
  26. package/src/style/components/forms/radio.js +80 -0
  27. package/src/style/components/index.js +5 -1
  28. package/src/style/helpers/index.js +3 -0
  29. package/src/style/payment-instruments/index.js +4 -0
  30. package/src/style/payment-instruments/payment-instrument-list.js +44 -0
  31. package/src/style/payment-instruments/payment-instrument.js +43 -0
  32. package/src/style/views/confirmation.js +0 -51
  33. package/src/views/method-selector/get-payment-methods.js +1 -1
  34. package/src/views/method-selector/mount-methods.js +126 -23
  35. package/tests/mocks/rebilly-api-mock.js +9 -0
  36. package/tests/mocks/rebilly-instruments-mock.js +22 -18
  37. package/tests/msw/server.js +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebilly/instruments",
3
- "version": "3.2.1-beta.0",
3
+ "version": "3.4.0-beta.0",
4
4
  "author": "Rebilly",
5
5
  "main": "dist/index.js",
6
6
  "unpkg": "dist/index.min.js",
@@ -5,7 +5,7 @@ import { fetchData } from './fetch-data';
5
5
  import setupElement from './setup-element';
6
6
  import setupStorefront from './setup-storefront';
7
7
  import setupOptions from './setup-options';
8
- import setupFramepay from './setup-framepay';
8
+ import setupFramepayInstance from './setup-framepay';
9
9
  import setupStyles from './setup-styles';
10
10
  import setupI18n from './setup-i18n';
11
11
  import setupFramepayTheme from './setup-framepay-theme';
@@ -63,11 +63,12 @@ import setupUserFlow from './setup-user-flow';
63
63
  * Mount library with configurations.
64
64
  * @param {object} options - The options object
65
65
  * @param {object} options.state - Global state
66
+ * @param {function} options.setupFramepayInstance - Helper for adding FramePay scripts to the DOM
66
67
  * @param {string | HTMLElement} options.form - The CSS class or HTML element were the form will be mounted.
67
68
  * @param {string | HTMLElement} options.summary - The CSS class or HTML element were the summary will be mounted.
68
69
  * @param {Item[]} options.items - Which plans the customer is purchasing.
69
70
  * @param {string} options.invoiceId - The Rebilly id of the invoice used for purchasing.
70
- * @param {string} options.customerJwt - The customer token to access the invoice.
71
+ * @param {string} options.jwt - The customer token to access the invoice.
71
72
  * @param {string} [options.countryCode=USD] - The country code for the transaction
72
73
  * @param {PaymentInstruments} options.paymentInstruments - settings for various payment instruments
73
74
  * @param {Features} options.features - flags to enable and disable different features
@@ -75,6 +76,7 @@ import setupUserFlow from './setup-user-flow';
75
76
  */
76
77
  export async function mount({
77
78
  state,
79
+ setupFramepay = setupFramepayInstance,
78
80
  ...options
79
81
  } = {}) {
80
82
  try {
@@ -100,7 +102,7 @@ export async function mount({
100
102
  state.options.themeFramepay = await setupFramepayTheme({ state, options });
101
103
  state.i18n = setupI18n({ state });
102
104
 
103
- setupFramepay({ state });
105
+ await setupFramepay(state);
104
106
 
105
107
  // Update state options from data
106
108
  if ((!state.options.websiteId) && state.data.transaction?.websiteId) {
@@ -8,9 +8,9 @@ import ProductModel from '@/storefront/models/product-model';
8
8
  import SummaryModel from '@/storefront/models/summary-model';
9
9
 
10
10
  describe('RebillyInstruments instance', () => {
11
- it("should inject HTML to the merchant's website", async () => {
11
+ it('should inject HTML to the merchant\'s website', async () => {
12
12
  const framePayScriptUrl = 'https://framepay.rebilly.com/rebilly.js';
13
- const framePayStyleUrl = 'https://dev.framepay.rebilly.com/rebilly.css';
13
+ const framePayStyleUrl = 'https://framepay.rebilly.com/rebilly.css';
14
14
 
15
15
  const options = {
16
16
  form: '.form-selector',
@@ -34,7 +34,6 @@ describe('RebillyInstruments instance', () => {
34
34
  framePayStyleLink: framePayStyleUrl
35
35
  },
36
36
  };
37
-
38
37
  await RenderMockRebillyInstruments(options);
39
38
 
40
39
  // Mounts form and summary
@@ -64,15 +63,14 @@ describe('RebillyInstruments instance', () => {
64
63
 
65
64
  // Mounts _dev FramePay style
66
65
  const STYLE_LINKS = [...document.querySelectorAll('head link')];
67
- const FRAMEPAY_STYLE = STYLE_LINKS.find(
68
- (script) => script.href === framePayStyleUrl
69
- );
66
+ const FRAMEPAY_STYLE = STYLE_LINKS.find(script => script.href === framePayStyleUrl);
67
+
70
68
  expect(FRAMEPAY_STYLE.href).toEqual(framePayStyleUrl);
71
69
  });
72
70
 
73
71
  it('should mount with JWT pruchase data', async () => {
74
72
  // Use https://www.jwt.io to help encode and decode JWT
75
- const jwt = `eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkMGYzNWEzYy03N2M0LTQ0NDItOWFhNC03ODA5NDA2NzBjN2IiLCJleHAiOjE2NzM2NDk0ODcsImlhdCI6MTY0MjExMDczOS4zMjYyNDQsImFjbCI6W3sic2NvcGUiOnsib3JnYW5pemF0aW9uSWQiOlsidGVzdC1vcmdhbml6YXRpb24tZCJdLCJ0cmFuc2FjdGlvbklkIjpbInRlc3QtdHJhbnNhY3Rpb24taWQiXX0sInBlcm1pc3Npb25zIjpbMV19XSwiY2xhaW1zIjp7InRyYW5zYWN0aW9uSWQiOiJ0ZXN0LXRyYW5zYWN0aW9uLWlkIn0sIm1lcmNoYW50IjoidGVzdC1vcmdhbml6YXRpb24taWQiLCJjdXN0b21lciI6eyJpZCI6InRlc3QtY3VzdG9tZXItaWQiLCJuYW1lIjoiVGVzdGVyIFRlc3RlcnNvbiIsImNyZWF0ZWRUaW1lIjoiMjAyMi0wMS0xNFQwMDowMDowMCswMDowMCJ9fQ.h4voW-UvXzXRm1JlxkN8cNHhQ_IIPSWWN9BANfBWEHQ`;
73
+ const jwt = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkMGYzNWEzYy03N2M0LTQ0NDItOWFhNC03ODA5NDA2NzBjN2IiLCJleHAiOjE2NzM2NDk0ODcsImlhdCI6MTY0MjExMDczOS4zMjYyNDQsImFjbCI6W3sic2NvcGUiOnsib3JnYW5pemF0aW9uSWQiOlsidGVzdC1vcmdhbml6YXRpb24tZCJdLCJ0cmFuc2FjdGlvbklkIjpbInRlc3QtdHJhbnNhY3Rpb24taWQiXX0sInBlcm1pc3Npb25zIjpbMV19XSwiY2xhaW1zIjp7InRyYW5zYWN0aW9uSWQiOiJ0ZXN0LXRyYW5zYWN0aW9uLWlkIn0sIm1lcmNoYW50IjoidGVzdC1vcmdhbml6YXRpb24taWQiLCJjdXN0b21lciI6eyJpZCI6InRlc3QtY3VzdG9tZXItaWQiLCJuYW1lIjoiVGVzdGVyIFRlc3RlcnNvbiIsImNyZWF0ZWRUaW1lIjoiMjAyMi0wMS0xNFQwMDowMDowMCswMDowMCJ9fQ.h4voW-UvXzXRm1JlxkN8cNHhQ_IIPSWWN9BANfBWEHQ';
76
74
 
77
75
  const options = {
78
76
  form: '.form-selector',
@@ -48,33 +48,56 @@ export default async ({
48
48
  const cssAst = css.parse(resolvedCss);
49
49
 
50
50
  const cssSelectors = {
51
- base: '.rebilly-instruments-form-field-input',
52
- baseHover: '.rebilly-instruments-form-field-input:hover',
53
- baseFocus: '.rebilly-instruments-form-field-input:focus',
54
- basePlaceholder: '.rebilly-instruments-form-field-input::placeholder',
55
- baseSelection: '.rebilly-instruments-form-field-input::selection',
56
-
57
- invalid: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input',
58
- invalidHover: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input:hover',
59
- invalidFocus: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input:focus',
60
- invalidPlaceholder: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input::placeholder',
61
- invalidSelection: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input::selection'
51
+ input: {
52
+ base: '.rebilly-instruments-form-field-input',
53
+ baseHover: '.rebilly-instruments-form-field-input:hover',
54
+ baseFocus: '.rebilly-instruments-form-field-input:focus',
55
+ basePlaceholder: '.rebilly-instruments-form-field-input::placeholder',
56
+ baseSelection: '.rebilly-instruments-form-field-input::selection',
57
+
58
+ invalid: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input',
59
+ invalidHover: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input:hover',
60
+ invalidFocus: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input:focus',
61
+ invalidPlaceholder: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input::placeholder',
62
+ invalidSelection: '.rebilly-instruments-form-field.is-error .rebilly-instruments-form-field-input::selection'
63
+ },
64
+ button: {
65
+ base: '.rebilly-instruments-button.rebilly-instruments-button-secondary',
66
+ baseHover: '.rebilly-instruments-button.rebilly-instruments-button-secondary:not([disabled]):hover',
67
+ baseFocus: '.rebilly-instruments-button.rebilly-instruments-button-secondary:not([disabled]):active',
68
+
69
+ active: '.rebilly-instruments-button',
70
+ activeHover: '.rebilly-instruments-button:not([disabled]):hover',
71
+ activeFocus: '.rebilly-instruments-button:not([disabled]):active',
72
+ }
62
73
  }
63
74
 
64
75
  const framepayStyle = {
65
76
  base: {
66
- ...getStyleProps(cssAst, cssSelectors.base),
67
- ':hover': getStyleProps(cssAst, cssSelectors.baseHover),
68
- ':focus': getStyleProps(cssAst, cssSelectors.baseFocus),
69
- '::placeholder': getStyleProps(cssAst, cssSelectors.basePlaceholder),
70
- '::selection': getStyleProps(cssAst, cssSelectors.baseSelection),
77
+ ...getStyleProps(cssAst, cssSelectors.input.base),
78
+ ':hover': getStyleProps(cssAst, cssSelectors.input.baseHover),
79
+ ':focus': getStyleProps(cssAst, cssSelectors.input.baseFocus),
80
+ '::placeholder': getStyleProps(cssAst, cssSelectors.input.basePlaceholder),
81
+ '::selection': getStyleProps(cssAst, cssSelectors.input.baseSelection),
71
82
  },
72
83
  invalid: {
73
- ...getStyleProps(cssAst, cssSelectors.invalid),
74
- ':hover': getStyleProps(cssAst, cssSelectors.invalidHover),
75
- ':focus': getStyleProps(cssAst, cssSelectors.invalidFocus),
76
- '::placeholder': getStyleProps(cssAst, cssSelectors.invalidPlaceholder),
77
- '::selection': getStyleProps(cssAst, cssSelectors.invalidSelection),
84
+ ...getStyleProps(cssAst, cssSelectors.input.invalid),
85
+ ':hover': getStyleProps(cssAst, cssSelectors.input.invalidHover),
86
+ ':focus': getStyleProps(cssAst, cssSelectors.input.invalidFocus),
87
+ '::placeholder': getStyleProps(cssAst, cssSelectors.input.invalidPlaceholder),
88
+ '::selection': getStyleProps(cssAst, cssSelectors.input.invalidSelection),
89
+ },
90
+ buttons: {
91
+ base: {
92
+ ...getStyleProps(cssAst, cssSelectors.button.base),
93
+ ':hover': getStyleProps(cssAst, cssSelectors.button.baseHover),
94
+ ':focus': getStyleProps(cssAst, cssSelectors.button.baseFocus),
95
+ },
96
+ active: {
97
+ ...getStyleProps(cssAst, cssSelectors.button.active),
98
+ ':hover': getStyleProps(cssAst, cssSelectors.button.activeHover),
99
+ ':focus': getStyleProps(cssAst, cssSelectors.button.activeFocus),
100
+ }
78
101
  }
79
102
  }
80
103
 
@@ -1,41 +1,20 @@
1
- import { addDOMElement } from '../../utils';
1
+ export default async function setupFramepay (state = {}) {
2
+ const {_dev} = state.options || {};
3
+ const urls = {
4
+ script: _dev?.framePayScriptLink || 'https://framepay.rebilly.com/rebilly.js',
5
+ style: _dev?.framePayStyleLink || 'https://framepay.rebilly.com/rebilly.css',
6
+ };
2
7
 
3
- export default ({
4
- state: {
5
- options: {
6
- _dev
7
- }
8
- }
9
- } = {}) => {
10
- const framePayUrls = {
11
- script: _dev
12
- ? _dev.framePayScriptLink || 'https://framepay.rebilly.com/rebilly.js'
13
- : 'https://framepay.rebilly.com/rebilly.js',
14
- style: _dev
15
- ? _dev.framePayStyleLink || 'https://framepay.rebilly.com/rebilly.css'
16
- : 'https://framepay.rebilly.com/rebilly.css'
17
- };
8
+ return new Promise((resolve) => {
9
+ const framepayStyle = document.createElement('link');
10
+ framepayStyle.setAttribute('href', urls.style);
11
+ framepayStyle.setAttribute('rel', 'stylesheet');
12
+ document.head.prepend(framepayStyle);
18
13
 
19
- if (!document.querySelectorAll('[framepay*="script"]').length) {
20
- addDOMElement({
21
- element: 'script',
22
- attributes: {
23
- framepay: 'script',
24
- src: framePayUrls.script
25
- },
26
- target: 'head'
14
+ const framepayScript = document.createElement('script');
15
+ framepayScript.setAttribute('src', urls.script);
16
+
17
+ framepayScript.onload = () => resolve();
18
+ document.head.append(framepayScript);
27
19
  });
28
- }
29
-
30
- if (!document.querySelectorAll('[framepay*="stylesheet"]').length) {
31
- addDOMElement({
32
- element: 'link',
33
- attributes: {
34
- framepay: 'stylesheet',
35
- href: framePayUrls.style,
36
- rel: 'stylesheet'
37
- },
38
- target: 'head'
39
- });
40
- }
41
- }
20
+ }
@@ -59,6 +59,10 @@ export function validateOptions(options) {
59
59
  }
60
60
 
61
61
  if (purchaseData.length > 1) {
62
+ // JWT can be alone or with specific invoiceId or transactionId
63
+ if (options.jwt && (options.invoiceId || options.transactionId)) {
64
+ return
65
+ }
62
66
  throw new Error('Must provide only one purchase data type');
63
67
  }
64
68
  }
@@ -66,6 +70,7 @@ export function validateOptions(options) {
66
70
  export default ({
67
71
  options = {}
68
72
  } = {}) => {
73
+
69
74
  validateOptions(options);
70
75
 
71
76
  const _computed = {
@@ -122,7 +127,7 @@ export default ({
122
127
  'money',
123
128
  'invoiceId',
124
129
  'transactionId',
125
- 'customerJwt',
130
+ 'jwt',
126
131
  '_dev'
127
132
  ].forEach(key => {
128
133
  if (options[key]) {
@@ -21,8 +21,7 @@ describe('Setup mount options', () => {
21
21
  publishableKey: 'test-publishable-key',
22
22
  organizationId: 'test-organization-id',
23
23
  websiteId: 'test-website-id',
24
- invoiceId: 'test-invoice-id',
25
- customerJwt: 'test-customer-jwt'
24
+ jwt: 'test-jwt'
26
25
  }
27
26
  const rebillyInstruments = await RenderMockRebillyInstruments(options);
28
27
  expect(rebillyInstruments.state.options).toMatchObject(options);
@@ -6,15 +6,24 @@ import { DataInstance } from './mount/fetch-data';
6
6
  export async function makePayment({ state, payload }) {
7
7
  const {
8
8
  _raw: {
9
- id: token
10
- }
9
+ id
10
+ },
11
+ isExistingInstrument
11
12
  } = payload;
13
+ delete payload.isExistingInstrument;
14
+ delete payload._raw;
12
15
 
13
16
  const data = {
14
- token,
15
17
  ...payload
16
18
  };
17
19
 
20
+ if (isExistingInstrument) {
21
+ data.paymentInstrumentId = id;
22
+
23
+ } else {
24
+ data.token = id;
25
+ }
26
+
18
27
  if (state.options.invoiceId) {
19
28
  data.invoiceId = state.options.invoiceId;
20
29
  }
@@ -36,7 +45,7 @@ export async function makePayment({ state, payload }) {
36
45
 
37
46
  fields = {
38
47
  transaction: fields,
39
- token: fields.token || state.options.customerJwt
48
+ token: fields.token || state.options.jwt
40
49
  };
41
50
 
42
51
  if (state.data.invoice) {
@@ -5,12 +5,30 @@ import { DataInstance } from './mount/fetch-data';
5
5
 
6
6
  export async function setup({ state, payload }) {
7
7
  try {
8
+ const {
9
+ _raw: {
10
+ id
11
+ },
12
+ isExistingInstrument
13
+ } = payload;
14
+ delete payload.isExistingInstrument;
15
+ delete payload._raw;
16
+
17
+ const data = {
18
+ ...payload
19
+ };
20
+
21
+ if (isExistingInstrument) {
22
+ data.paymentInstrumentId = id;
23
+ } else {
24
+ data.token = id;
25
+ }
26
+
8
27
  const {instrument, transaction} = await setupPaymentInstrument({
9
28
  state,
10
29
  data: {
11
- token: payload._raw.id,
12
30
  websiteId: state.options?.websiteId,
13
- ...payload
31
+ ...data
14
32
  }
15
33
  });
16
34
 
package/src/i18n/en.json CHANGED
@@ -11,6 +11,7 @@
11
11
  "expressCheckout": "Express checkout",
12
12
  "or": "Or",
13
13
  "popupOverlayText": "Click here to show popup window",
14
+ "andMore": "and more",
14
15
  "error": {
15
16
  "noPaymentMethods": "No payment methods available for this transaction, please contact support."
16
17
  },
@@ -19,7 +20,8 @@
19
20
  }
20
21
  },
21
22
  "paymentMethods": {
22
- "payment-card": "Payment card"
23
+ "payment-card": "Payment card",
24
+ "ach": "Bank account"
23
25
  }
24
26
  }
25
27
  }
package/src/i18n/es.json CHANGED
@@ -10,13 +10,15 @@
10
10
  "form": {
11
11
  "expressCheckout": "Chequeo rápido",
12
12
  "or": "O pague con",
13
+ "andMore": "y más",
13
14
  "popupOverlayText": "Haga clic aquí para mostrar la ventana emergente",
14
15
  "error": {
15
16
  "noPaymentMethods": "No hay métodos de pago disponibles para esta transacción, por favor, póngase en contacto con el servicio de asistencia."
16
17
  }
17
18
  },
18
19
  "paymentMethods": {
19
- "payment-card": "Tarjeta de crédito"
20
+ "payment-card": "Tarjeta de crédito",
21
+ "ach": "Cuenta bancaria"
20
22
  }
21
23
  }
22
24
  }
@@ -1,6 +1,7 @@
1
+ import { avoidUnhandledPromises } from 'tests/async-utilities';
2
+ import { setupFramepayMock } from 'tests/mocks/rebilly-instruments-mock';
1
3
  import RebillyInstruments from './index';
2
4
  import { RebillyInstrumentsInstance } from './instance';
3
- import { avoidUnhandledPromises } from 'tests/async-utilities';
4
5
 
5
6
  describe('RebillyInstruments instance', () => {
6
7
  let rebillyInstruments;
@@ -24,7 +25,8 @@ describe('RebillyInstruments instance', () => {
24
25
  const options = {
25
26
  form: '.form-selector',
26
27
  summary: '.summary-selector',
27
- items: []
28
+ items: [],
29
+ setupFramepay: setupFramepayMock,
28
30
  };
29
31
 
30
32
  await rebillyInstruments.mount(options);
@@ -1,4 +1,4 @@
1
- import { RebillyStorefrontAPI } from 'rebilly-js-sdk';
1
+ import RebillyApi, {RebillyStorefrontAPI} from 'rebilly-js-sdk';
2
2
 
3
3
  export function validateStateForStorefront({state}) {
4
4
  if (!state.storefront) {
@@ -43,23 +43,25 @@ export class StorefrontInstance {
43
43
  sandbox: sandboxUrl || 'https://api-sandbox.rebilly.com'
44
44
  };
45
45
 
46
- const api = RebillyStorefrontAPI({
46
+ const config = {
47
47
  organizationId,
48
48
  sandbox: mode === 'sandbox',
49
49
  timeout: Number.isNaN(parseInt(timeout, 10))
50
50
  ? 10000
51
51
  : parseInt(timeout, 10),
52
52
  urls
53
- });
53
+ };
54
54
 
55
- if (publishableKey) {
56
- api.setPublishableKey(publishableKey);
57
- }
58
- if (jwt) {
59
- api.setSessionToken(jwt);
60
- }
55
+ const api = RebillyStorefrontAPI(config);
56
+ // TODO: Check why Rollup is making the default as an named export
57
+ const rebilly = typeof RebillyApi.default === 'function' ? RebillyApi.default(config) : RebillyApi(config);
58
+
59
+ api.setSessionToken(publishableKey || jwt);
60
+ rebilly.setSessionToken(publishableKey || jwt);
61
61
 
62
62
  this.api = api;
63
+ this.api.rebilly = rebilly;
64
+
63
65
  return this.api;
64
66
  }
65
67
  }
@@ -3,7 +3,7 @@ import { Endpoint } from './index';
3
3
 
4
4
  export async function fetchInvoice({ data = null, state = null }) {
5
5
  return Endpoint({state}, async () => {
6
- state.storefront.setSessionToken(state.options.customerJwt || state.options.jwt);
6
+ state.storefront.setSessionToken(state.options.jwt);
7
7
  const {fields} = await state.storefront.invoices.get(data);
8
8
 
9
9
  return new InvoiceModel(fields);
@@ -0,0 +1,7 @@
1
+ import BaseModel from './base-model';
2
+
3
+ export default class PaymentMetadataModel extends BaseModel {
4
+ get logo () {
5
+ return this.landscapeLogo || this.portraitLogo;
6
+ }
7
+ }
@@ -1,3 +1,5 @@
1
+ import PaymentMetadataModel from './payment-metadata';
2
+
1
3
  export class ReadyToPayFeatureModel {
2
4
  constructor({
3
5
  name = '',
@@ -16,6 +18,7 @@ export class ReadyToPayFeatureModel {
16
18
  } = {}) {
17
19
  this.name = name;
18
20
  this.expirationTime = expirationTime;
21
+
19
22
 
20
23
  this.merchantName = merchantName;
21
24
  this.merchantOrigin = merchantOrigin;
@@ -33,12 +36,14 @@ export default class ReadyToPayModel {
33
36
  method = '',
34
37
  feature = null,
35
38
  brands = [],
36
- filters = []
39
+ filters = [],
40
+ metadata = null
37
41
  } = {}) {
38
42
  this.index = index;
39
43
  this.method = method;
40
44
  this.feature = feature ? new ReadyToPayFeatureModel(feature) : null;
41
45
  this.brands = brands;
42
46
  this.filters = filters;
47
+ this.metadata = metadata ? new PaymentMetadataModel(metadata) : null;
43
48
  }
44
49
  }
@@ -16,10 +16,10 @@ export async function setupPaymentInstrument({ data, state }) {
16
16
  }
17
17
  }
18
18
 
19
- if(state.data.getAmountAndCurrency) {
19
+ if(state.data.amountAndCurrency) {
20
20
  setupPayload.data = {
21
21
  ...setupPayload.data,
22
- ...state.data.getAmountAndCurrency
22
+ ...state.data.amountAndCurrency
23
23
  }
24
24
  }
25
25
 
@@ -33,16 +33,30 @@ export async function fetchReadyToPay({ state, riskMetadata = null }) {
33
33
  data.currency = money.currency;
34
34
  }
35
35
 
36
- const { fields: readyToPayFields } =
37
- await state.storefront.purchase.readyToPay({ data });
36
+ const [
37
+ { fields: readyToPayFields },
38
+ { items: paymentMethodsMetadataItems }
39
+ ] = await Promise.all([
40
+ state.storefront.purchase.readyToPay({ data }),
41
+ state.storefront.rebilly.paymentMethods.getAll()
42
+ ]);
43
+
44
+ const paymentMethodsMetadata = paymentMethodsMetadataItems.map(({fields}) => fields);
38
45
 
39
46
  return Object.values(readyToPayFields)
40
47
  // Remove result for "old" paypal method
41
48
  .filter((fields) => !(fields.method === 'paypal' && !fields.feature))
42
- .map((fields, index) => new ReadyToPayModel({
49
+ // Remove Plaid payment method
50
+ .filter((fields) => !(fields.method === 'ach' && fields.feature))
51
+ .map((fields, index) => {
52
+ const metadata = paymentMethodsMetadata
53
+ .find(methodMetadata => methodMetadata.apiName === fields.method);
54
+
55
+ return new ReadyToPayModel({
43
56
  index,
57
+ metadata,
44
58
  ...fields
45
- })
46
- );
59
+ });
60
+ });
47
61
  });
48
62
  }
@@ -3,7 +3,7 @@ import { Endpoint } from './index';
3
3
 
4
4
  export async function fetchTransaction({ data = null, state = null }) {
5
5
  return Endpoint({state}, async () => {
6
- state.storefront.setSessionToken(state.options.customerJwt || state.options.jwt);
6
+ state.storefront.setSessionToken(state.options.jwt);
7
7
  const {fields} = await state.storefront.transactions.get(data);
8
8
 
9
9
  return new TransactionModel(fields);