@justifi/webcomponents 0.2.2 → 0.4.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/CHANGELOG.md +11 -0
- package/dist/cjs/Payment-5781460e.js +71 -0
- package/dist/cjs/{index-ca2cd154.js → index-4f2a13d2.js} +13 -389
- package/dist/cjs/justifi-bank-account-form.cjs.entry.js +3 -2
- package/dist/cjs/{justifi-billing-form.cjs.entry.js → justifi-billing-form_2.cjs.entry.js} +33 -2
- package/dist/cjs/justifi-card-form.cjs.entry.js +3 -2
- package/dist/cjs/justifi-payment-form.cjs.entry.js +46 -3
- package/dist/cjs/justifi-payment-method-form.cjs.entry.js +28 -17
- package/dist/cjs/justifi-payments-list.cjs.entry.js +3 -70
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/cjs/select-input_2.cjs.entry.js +2 -4
- package/dist/cjs/webcomponents.cjs.js +2 -2
- package/dist/collection/api/Payment.js +1 -1
- package/dist/collection/collection-manifest.json +1 -0
- package/dist/collection/components/bank-account-form/bank-account-form.js +21 -3
- package/dist/collection/components/billing-form/billing-form.js +73 -1
- package/dist/collection/components/billing-form/billing-form.stories.js +14 -0
- package/dist/collection/components/card-form/card-form.js +21 -3
- package/dist/collection/components/card-form/card-form.stories.js +35 -28
- package/dist/collection/components/payment-form/payment-form.js +145 -7
- package/dist/collection/components/payment-form/payment-form.stories.js +82 -0
- package/dist/collection/components/payment-form/payment-method-selector.js +86 -0
- package/dist/collection/components/payment-form/tokenize.js +1 -0
- package/dist/collection/components/payment-method-form/payment-method-form.js +22 -2
- package/dist/collection/components/select-input/select-input.js +1 -3
- package/dist/components/Payment.js +69 -0
- package/dist/components/billing-form.js +2188 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/justifi-bank-account-form.js +5 -3
- package/dist/components/justifi-billing-form.js +1 -2175
- package/dist/components/justifi-card-form.js +5 -3
- package/dist/components/justifi-payment-form.js +85 -6
- package/dist/components/justifi-payment-method-selector.d.ts +11 -0
- package/dist/components/justifi-payment-method-selector.js +6 -0
- package/dist/components/justifi-payments-list.js +1 -68
- package/dist/components/payment-method-form.js +29 -17
- package/dist/components/payment-method-selector.js +42 -0
- package/dist/components/select-input2.js +1 -3
- package/dist/esm/Payment-3f7570a8.js +69 -0
- package/dist/esm/{index-05706eb5.js → index-3ce5521c.js} +13 -389
- package/dist/esm/justifi-bank-account-form.entry.js +3 -2
- package/dist/esm/{justifi-billing-form.entry.js → justifi-billing-form_2.entry.js} +33 -3
- package/dist/esm/justifi-card-form.entry.js +3 -2
- package/dist/esm/justifi-payment-form.entry.js +46 -3
- package/dist/esm/justifi-payment-method-form.entry.js +28 -17
- package/dist/esm/justifi-payments-list.entry.js +2 -69
- package/dist/esm/loader.js +2 -2
- package/dist/esm/select-input_2.entry.js +2 -4
- package/dist/esm/webcomponents.js +2 -2
- package/dist/types/api/Payment.d.ts +1 -1
- package/dist/types/components/bank-account-form/bank-account-form.d.ts +1 -0
- package/dist/types/components/billing-form/billing-form-schema.d.ts +7 -0
- package/dist/types/components/billing-form/billing-form.d.ts +5 -8
- package/dist/types/components/billing-form/billing-form.stories.d.ts +7 -0
- package/dist/types/components/card-form/card-form.d.ts +1 -0
- package/dist/types/components/card-form/card-form.stories.d.ts +1 -0
- package/dist/types/components/payment-form/payment-form.d.ts +17 -1
- package/dist/types/components/payment-form/payment-form.stories.d.ts +44 -0
- package/dist/types/components/payment-form/payment-method-selector.d.ts +10 -0
- package/dist/types/components/payment-form/tokenize.d.ts +5 -0
- package/dist/types/components/payment-method-form/payment-method-form.d.ts +1 -0
- package/dist/types/components.d.ts +42 -2
- package/dist/webcomponents/p-21e020a8.js +1 -0
- package/dist/webcomponents/p-2e5be95e.entry.js +1 -0
- package/dist/webcomponents/p-6633de1b.entry.js +1 -0
- package/dist/webcomponents/p-68e47ee5.entry.js +1 -0
- package/dist/webcomponents/p-6a9c764f.entry.js +1 -0
- package/dist/webcomponents/p-6c3a226e.entry.js +1 -0
- package/dist/webcomponents/{p-3809130a.entry.js → p-763a2b4f.entry.js} +1 -1
- package/dist/webcomponents/p-92ca574f.entry.js +1 -0
- package/dist/webcomponents/p-9f34a2c1.js +2 -0
- package/dist/webcomponents/webcomponents.esm.js +1 -1
- package/package.json +23 -15
- package/dist/webcomponents/p-4009b629.entry.js +0 -1
- package/dist/webcomponents/p-787671b9.entry.js +0 -1
- package/dist/webcomponents/p-87654bf4.entry.js +0 -1
- package/dist/webcomponents/p-8ee06fd1.js +0 -2
- package/dist/webcomponents/p-94ef2d0e.entry.js +0 -1
- package/dist/webcomponents/p-c07191dc.entry.js +0 -1
- package/dist/webcomponents/p-e5b0f047.entry.js +0 -1
|
@@ -3,6 +3,7 @@ export class CardForm {
|
|
|
3
3
|
constructor() {
|
|
4
4
|
this.validationStrategy = undefined;
|
|
5
5
|
this.styleOverrides = undefined;
|
|
6
|
+
this.iframeOrigin = undefined;
|
|
6
7
|
this.internalStyleOverrides = undefined;
|
|
7
8
|
}
|
|
8
9
|
readyHandler(event) {
|
|
@@ -40,14 +41,14 @@ export class CardForm {
|
|
|
40
41
|
if (el) {
|
|
41
42
|
this.childRef = el;
|
|
42
43
|
}
|
|
43
|
-
}, "payment-method-form-type": "card", "payment-method-form-ready": this.cardFormReady, "payment-method-form-tokenize": this.cardFormTokenize, "payment-method-form-validation-strategy": this.validationStrategy || 'onSubmit', paymentMethodStyleOverrides: this.internalStyleOverrides }));
|
|
44
|
+
}, "iframe-origin": this.iframeOrigin, "payment-method-form-type": "card", "payment-method-form-ready": this.cardFormReady, "payment-method-form-tokenize": this.cardFormTokenize, "payment-method-form-validation-strategy": this.validationStrategy || 'onSubmit', paymentMethodStyleOverrides: this.internalStyleOverrides }));
|
|
44
45
|
}
|
|
45
46
|
static get is() { return "justifi-card-form"; }
|
|
46
47
|
static get properties() {
|
|
47
48
|
return {
|
|
48
49
|
"validationStrategy": {
|
|
49
50
|
"type": "string",
|
|
50
|
-
"mutable":
|
|
51
|
+
"mutable": true,
|
|
51
52
|
"complexType": {
|
|
52
53
|
"original": "'onChange' | 'onBlur' | 'onSubmit' | 'onTouched' | 'all'",
|
|
53
54
|
"resolved": "\"all\" | \"onBlur\" | \"onChange\" | \"onSubmit\" | \"onTouched\"",
|
|
@@ -64,7 +65,7 @@ export class CardForm {
|
|
|
64
65
|
},
|
|
65
66
|
"styleOverrides": {
|
|
66
67
|
"type": "string",
|
|
67
|
-
"mutable":
|
|
68
|
+
"mutable": true,
|
|
68
69
|
"complexType": {
|
|
69
70
|
"original": "string",
|
|
70
71
|
"resolved": "string",
|
|
@@ -78,6 +79,23 @@ export class CardForm {
|
|
|
78
79
|
},
|
|
79
80
|
"attribute": "style-overrides",
|
|
80
81
|
"reflect": false
|
|
82
|
+
},
|
|
83
|
+
"iframeOrigin": {
|
|
84
|
+
"type": "string",
|
|
85
|
+
"mutable": true,
|
|
86
|
+
"complexType": {
|
|
87
|
+
"original": "string",
|
|
88
|
+
"resolved": "string",
|
|
89
|
+
"references": {}
|
|
90
|
+
},
|
|
91
|
+
"required": false,
|
|
92
|
+
"optional": true,
|
|
93
|
+
"docs": {
|
|
94
|
+
"tags": [],
|
|
95
|
+
"text": ""
|
|
96
|
+
},
|
|
97
|
+
"attribute": "iframe-origin",
|
|
98
|
+
"reflect": false
|
|
81
99
|
}
|
|
82
100
|
};
|
|
83
101
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { userEvent, within } from '@storybook/testing-library';
|
|
2
|
+
import { expect } from '@storybook/jest';
|
|
1
3
|
export default {
|
|
2
4
|
title: 'Components/CardForm',
|
|
3
5
|
component: 'justifi-card-form',
|
|
@@ -17,33 +19,26 @@ export default {
|
|
|
17
19
|
`,
|
|
18
20
|
],
|
|
19
21
|
};
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
+
const handleValidateClick = async (cardForm) => {
|
|
23
|
+
const valid = await cardForm.validate();
|
|
24
|
+
console.log(valid);
|
|
22
25
|
};
|
|
23
|
-
|
|
24
|
-
// Only use named functions when binding to event handlers. Otherwise, they will be bound multiple times
|
|
25
|
-
// Going forward, we could create a decorator that binds events
|
|
26
|
-
const handleValidateClick = () => {
|
|
27
|
-
const cardForm = document.querySelector('justifi-card-form');
|
|
28
|
-
cardForm.validate();
|
|
29
|
-
console.log('validate');
|
|
30
|
-
};
|
|
31
|
-
const handleTokenizeClick = async () => {
|
|
32
|
-
const cardForm = document.querySelector('justifi-card-form');
|
|
26
|
+
const handleTokenizeClick = async (cardForm, paymentMethodData) => {
|
|
33
27
|
const tokenizeResponse = await cardForm.tokenize('CLIENT_ID', paymentMethodData);
|
|
34
28
|
console.log(tokenizeResponse);
|
|
35
29
|
};
|
|
36
|
-
const
|
|
30
|
+
const handleReady = () => {
|
|
31
|
+
console.log('card form is ready');
|
|
32
|
+
const cardForm = document.querySelector('justifi-card-form');
|
|
37
33
|
const validateBtn = document.querySelector('#validate-btn');
|
|
38
34
|
const tokenizeBtn = document.querySelector('#tokenize-btn');
|
|
39
|
-
validateBtn === null || validateBtn === void 0 ? void 0 : validateBtn.addEventListener('click', handleValidateClick);
|
|
40
|
-
tokenizeBtn === null || tokenizeBtn === void 0 ? void 0 : tokenizeBtn.addEventListener('click', handleTokenizeClick);
|
|
35
|
+
validateBtn === null || validateBtn === void 0 ? void 0 : validateBtn.addEventListener('click', () => { handleValidateClick(cardForm); });
|
|
36
|
+
tokenizeBtn === null || tokenizeBtn === void 0 ? void 0 : tokenizeBtn.addEventListener('click', () => { handleTokenizeClick(cardForm, {}); });
|
|
41
37
|
};
|
|
42
38
|
const addEvents = () => {
|
|
43
|
-
addEventListener('cardFormReady',
|
|
39
|
+
addEventListener('cardFormReady', handleReady);
|
|
44
40
|
};
|
|
45
|
-
|
|
46
|
-
const buttons = `
|
|
41
|
+
const FormButtons = `
|
|
47
42
|
<style>
|
|
48
43
|
.button-bar {
|
|
49
44
|
display: flex;
|
|
@@ -96,24 +91,17 @@ const storyStyleOverrides = {
|
|
|
96
91
|
"fontSize": ".875rem"
|
|
97
92
|
}
|
|
98
93
|
};
|
|
99
|
-
const Template = ({ includeButtons, styleOverrides }) => {
|
|
94
|
+
const Template = ({ includeButtons = true, styleOverrides }) => {
|
|
100
95
|
const parsedStyleOverrides = styleOverrides ? JSON.stringify(styleOverrides) : null;
|
|
101
|
-
// The <div> here should be replaced by a `display` property in the cardForm potentially
|
|
102
96
|
return (`
|
|
103
97
|
<div>
|
|
104
|
-
<justifi-card-form style-overrides='${parsedStyleOverrides || ''}' />
|
|
98
|
+
<justifi-card-form data-testid="card-form-iframe" style-overrides='${parsedStyleOverrides || ''}' />
|
|
105
99
|
</div>
|
|
106
|
-
${includeButtons ?
|
|
100
|
+
${includeButtons ? FormButtons : ''}
|
|
107
101
|
`);
|
|
108
102
|
};
|
|
109
103
|
export const Basic = Template.bind({});
|
|
110
|
-
Basic.args = {
|
|
111
|
-
includeButtons: true
|
|
112
|
-
};
|
|
113
104
|
export const Embedded = Template.bind({});
|
|
114
|
-
Embedded.args = {
|
|
115
|
-
includeButtons: true
|
|
116
|
-
};
|
|
117
105
|
Embedded.decorators = [
|
|
118
106
|
(story) => `
|
|
119
107
|
<style>
|
|
@@ -130,3 +118,22 @@ export const Styled = Template.bind({});
|
|
|
130
118
|
Styled.args = {
|
|
131
119
|
styleOverrides: storyStyleOverrides
|
|
132
120
|
};
|
|
121
|
+
export const Completed = Template.bind({});
|
|
122
|
+
Completed.play = async ({ canvasElement, step }) => {
|
|
123
|
+
// Need to wait for iFrame to load
|
|
124
|
+
addEventListener('cardFormReady', async () => {
|
|
125
|
+
const canvas = within(canvasElement);
|
|
126
|
+
await step('CardForm is rendered', async () => {
|
|
127
|
+
expect(canvas.getByTestId('card-form-iframe')).toBeDefined();
|
|
128
|
+
});
|
|
129
|
+
await step('Validate form when empty shows errors', async () => {
|
|
130
|
+
userEvent.click(canvas.getByRole('button', { name: 'Validate' }));
|
|
131
|
+
});
|
|
132
|
+
// Expect errors to show up, but can't figure out how to get them
|
|
133
|
+
await step('Call tokenize with empty form shows errors', async () => {
|
|
134
|
+
userEvent.click(canvas.getByRole('button', { name: 'Tokenize' }));
|
|
135
|
+
});
|
|
136
|
+
// Expect errors to show up, but can't figure out how to get them
|
|
137
|
+
// Fill form
|
|
138
|
+
});
|
|
139
|
+
};
|
|
@@ -1,31 +1,169 @@
|
|
|
1
1
|
import { h, Host } from '@stencil/core';
|
|
2
|
+
import { PaymentMethodTypes } from '../../api';
|
|
2
3
|
export class PaymentForm {
|
|
3
4
|
constructor() {
|
|
4
|
-
this.
|
|
5
|
+
this.bankAccount = undefined;
|
|
6
|
+
this.card = undefined;
|
|
7
|
+
this.iframeOrigin = undefined;
|
|
8
|
+
this.selectedPaymentMethodType = undefined;
|
|
9
|
+
this.allowedPaymentMethodTypes = [];
|
|
10
|
+
}
|
|
11
|
+
connectedCallback() {
|
|
12
|
+
if (this.card) {
|
|
13
|
+
this.allowedPaymentMethodTypes.push(PaymentMethodTypes.card);
|
|
14
|
+
}
|
|
15
|
+
if (this.bankAccount) {
|
|
16
|
+
this.allowedPaymentMethodTypes.push(PaymentMethodTypes.bankAccount);
|
|
17
|
+
}
|
|
18
|
+
if (!this.allowedPaymentMethodTypes.length) {
|
|
19
|
+
this.allowedPaymentMethodTypes.push(PaymentMethodTypes.card);
|
|
20
|
+
}
|
|
21
|
+
this.selectedPaymentMethodType = this.allowedPaymentMethodTypes[0];
|
|
22
|
+
}
|
|
23
|
+
paymentMethodSelectedHandler(event) {
|
|
24
|
+
const paymentMethodType = event.detail;
|
|
25
|
+
this.selectedPaymentMethodType = paymentMethodType;
|
|
26
|
+
}
|
|
27
|
+
async fillBillingForm(fields) {
|
|
28
|
+
this.billingFormRef.fill(fields);
|
|
29
|
+
}
|
|
30
|
+
async submit(args) {
|
|
31
|
+
if (!this.paymentMethodFormRef || !this.billingFormRef)
|
|
32
|
+
return;
|
|
33
|
+
const billingFormValidation = await this.billingFormRef.validate();
|
|
34
|
+
const paymentMethodFormValidation = await this.paymentMethodFormRef.validate();
|
|
35
|
+
if (!billingFormValidation.isValid || !paymentMethodFormValidation.isValid)
|
|
36
|
+
return;
|
|
37
|
+
const billingFormFieldValues = await this.billingFormRef.getValues();
|
|
38
|
+
const paymentMethodData = Object.assign(Object.assign({}, args.paymentMethodData), billingFormFieldValues);
|
|
39
|
+
return this.paymentMethodFormRef.tokenize(args.clientId, paymentMethodData, args.accountId);
|
|
5
40
|
}
|
|
6
41
|
render() {
|
|
7
|
-
return (h(Host, null, h("form", null, h("
|
|
42
|
+
return (h(Host, null, h("form", null, (this.allowedPaymentMethodTypes.length > 1) && (h("justifi-payment-method-selector", { paymentMethodTypes: this.allowedPaymentMethodTypes, selectedPaymentMethodType: this.selectedPaymentMethodType })), h("justifi-payment-method-form", { "payment-method-form-type": this.selectedPaymentMethodType, "iframe-origin": this.iframeOrigin, ref: el => {
|
|
43
|
+
if (el) {
|
|
44
|
+
this.paymentMethodFormRef = el;
|
|
45
|
+
}
|
|
46
|
+
} }), h("justifi-billing-form", { legend: "Billing Info", ref: el => {
|
|
47
|
+
if (el) {
|
|
48
|
+
this.billingFormRef = el;
|
|
49
|
+
}
|
|
50
|
+
} }))));
|
|
8
51
|
}
|
|
9
52
|
static get is() { return "justifi-payment-form"; }
|
|
10
53
|
static get properties() {
|
|
11
54
|
return {
|
|
12
|
-
"
|
|
55
|
+
"bankAccount": {
|
|
56
|
+
"type": "boolean",
|
|
57
|
+
"mutable": false,
|
|
58
|
+
"complexType": {
|
|
59
|
+
"original": "boolean",
|
|
60
|
+
"resolved": "boolean",
|
|
61
|
+
"references": {}
|
|
62
|
+
},
|
|
63
|
+
"required": false,
|
|
64
|
+
"optional": true,
|
|
65
|
+
"docs": {
|
|
66
|
+
"tags": [],
|
|
67
|
+
"text": ""
|
|
68
|
+
},
|
|
69
|
+
"attribute": "bank-account",
|
|
70
|
+
"reflect": false
|
|
71
|
+
},
|
|
72
|
+
"card": {
|
|
73
|
+
"type": "boolean",
|
|
74
|
+
"mutable": false,
|
|
75
|
+
"complexType": {
|
|
76
|
+
"original": "boolean",
|
|
77
|
+
"resolved": "boolean",
|
|
78
|
+
"references": {}
|
|
79
|
+
},
|
|
80
|
+
"required": false,
|
|
81
|
+
"optional": true,
|
|
82
|
+
"docs": {
|
|
83
|
+
"tags": [],
|
|
84
|
+
"text": ""
|
|
85
|
+
},
|
|
86
|
+
"attribute": "card",
|
|
87
|
+
"reflect": false
|
|
88
|
+
},
|
|
89
|
+
"iframeOrigin": {
|
|
13
90
|
"type": "string",
|
|
14
91
|
"mutable": false,
|
|
15
92
|
"complexType": {
|
|
16
|
-
"original": "
|
|
17
|
-
"resolved": "
|
|
93
|
+
"original": "string",
|
|
94
|
+
"resolved": "string",
|
|
18
95
|
"references": {}
|
|
19
96
|
},
|
|
20
97
|
"required": false,
|
|
21
|
-
"optional":
|
|
98
|
+
"optional": true,
|
|
22
99
|
"docs": {
|
|
23
100
|
"tags": [],
|
|
24
101
|
"text": ""
|
|
25
102
|
},
|
|
26
|
-
"attribute": "
|
|
103
|
+
"attribute": "iframe-origin",
|
|
27
104
|
"reflect": false
|
|
28
105
|
}
|
|
29
106
|
};
|
|
30
107
|
}
|
|
108
|
+
static get states() {
|
|
109
|
+
return {
|
|
110
|
+
"selectedPaymentMethodType": {},
|
|
111
|
+
"allowedPaymentMethodTypes": {}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
static get methods() {
|
|
115
|
+
return {
|
|
116
|
+
"fillBillingForm": {
|
|
117
|
+
"complexType": {
|
|
118
|
+
"signature": "(fields: BillingFormFields) => Promise<void>",
|
|
119
|
+
"parameters": [{
|
|
120
|
+
"tags": [],
|
|
121
|
+
"text": ""
|
|
122
|
+
}],
|
|
123
|
+
"references": {
|
|
124
|
+
"Promise": {
|
|
125
|
+
"location": "global"
|
|
126
|
+
},
|
|
127
|
+
"BillingFormFields": {
|
|
128
|
+
"location": "import",
|
|
129
|
+
"path": "../billing-form/billing-form-schema"
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
"return": "Promise<void>"
|
|
133
|
+
},
|
|
134
|
+
"docs": {
|
|
135
|
+
"text": "",
|
|
136
|
+
"tags": []
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"submit": {
|
|
140
|
+
"complexType": {
|
|
141
|
+
"signature": "(args: { clientId: string; paymentMethodData: any; accountId?: string; }) => Promise<any>",
|
|
142
|
+
"parameters": [{
|
|
143
|
+
"tags": [],
|
|
144
|
+
"text": ""
|
|
145
|
+
}],
|
|
146
|
+
"references": {
|
|
147
|
+
"Promise": {
|
|
148
|
+
"location": "global"
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
"return": "Promise<any>"
|
|
152
|
+
},
|
|
153
|
+
"docs": {
|
|
154
|
+
"text": "",
|
|
155
|
+
"tags": []
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
static get listeners() {
|
|
161
|
+
return [{
|
|
162
|
+
"name": "paymentMethodSelected",
|
|
163
|
+
"method": "paymentMethodSelectedHandler",
|
|
164
|
+
"target": undefined,
|
|
165
|
+
"capture": false,
|
|
166
|
+
"passive": false
|
|
167
|
+
}];
|
|
168
|
+
}
|
|
31
169
|
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const Template = (args) => {
|
|
2
|
+
// The <div> here should be replaced by a `display` property in the cardForm potentially
|
|
3
|
+
return (`
|
|
4
|
+
<div>
|
|
5
|
+
<justifi-payment-form card=${args.card} bank-account=${args['bank-account']} />
|
|
6
|
+
</div>
|
|
7
|
+
<div>
|
|
8
|
+
<button id="submit-button">Submit</button>
|
|
9
|
+
</div>
|
|
10
|
+
<script>
|
|
11
|
+
(async () => {
|
|
12
|
+
await customElements.whenDefined('justifi-payment-form');
|
|
13
|
+
const paymentForm = document.querySelector('justifi-payment-form');
|
|
14
|
+
const submitButton = document.querySelector('#submit-button');
|
|
15
|
+
|
|
16
|
+
paymentForm.iframeOrigin = 'http://localhost:3003/v2';
|
|
17
|
+
|
|
18
|
+
submitButton?.addEventListener('click', async () => {
|
|
19
|
+
const tokenizeResponse = await paymentForm.submit({
|
|
20
|
+
clientId: '${args.clientId}',
|
|
21
|
+
paymentMethodData: ${JSON.stringify(args.paymentMethodData)},
|
|
22
|
+
accountId: '${args.accountId}'
|
|
23
|
+
});
|
|
24
|
+
console.log('tokenizeResponse:', tokenizeResponse);
|
|
25
|
+
});
|
|
26
|
+
})()
|
|
27
|
+
</script>
|
|
28
|
+
`);
|
|
29
|
+
};
|
|
30
|
+
export default {
|
|
31
|
+
title: 'Components/PaymentForm',
|
|
32
|
+
component: 'justifi-payment-form',
|
|
33
|
+
argTypes: {
|
|
34
|
+
'bank-account': {
|
|
35
|
+
control: 'boolean',
|
|
36
|
+
table: {
|
|
37
|
+
category: 'Props'
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
card: {
|
|
41
|
+
control: 'boolean',
|
|
42
|
+
table: {
|
|
43
|
+
category: 'Props'
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
accountId: {
|
|
47
|
+
control: 'text',
|
|
48
|
+
table: {
|
|
49
|
+
category: 'Tokenize Arguments'
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
clientId: {
|
|
53
|
+
control: 'text',
|
|
54
|
+
table: {
|
|
55
|
+
category: 'Tokenize Arguments'
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
paymentMethodData: {
|
|
59
|
+
control: 'object',
|
|
60
|
+
table: {
|
|
61
|
+
category: 'Tokenize Arguments'
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
parameters: {
|
|
66
|
+
actions: {
|
|
67
|
+
handles: [],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
decorators: [
|
|
71
|
+
(story) => story(),
|
|
72
|
+
],
|
|
73
|
+
};
|
|
74
|
+
export const Basic = Template.bind({});
|
|
75
|
+
Basic.args = {
|
|
76
|
+
'bank-account': true,
|
|
77
|
+
card: true,
|
|
78
|
+
clientId: '',
|
|
79
|
+
paymentMethodData: {},
|
|
80
|
+
accountId: '',
|
|
81
|
+
iframeOrigin: ''
|
|
82
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { h } from '@stencil/core';
|
|
2
|
+
const PaymentMethodLabels = {
|
|
3
|
+
bankAccount: 'Bank Account',
|
|
4
|
+
card: 'Card'
|
|
5
|
+
};
|
|
6
|
+
export class PaymentMethodSelector {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.paymentMethodTypes = [];
|
|
9
|
+
this.selectedPaymentMethodType = undefined;
|
|
10
|
+
}
|
|
11
|
+
onChangeHandler(event) {
|
|
12
|
+
this.paymentMethodSelected.emit(event.target.value);
|
|
13
|
+
}
|
|
14
|
+
render() {
|
|
15
|
+
return (h("div", null, this.paymentMethodTypes.map((paymentMethodType) => {
|
|
16
|
+
return (h("div", null, h("input", { id: paymentMethodType, type: "radio", name: "paymentMethodType", value: paymentMethodType, onChange: (event) => this.onChangeHandler(event), checked: this.selectedPaymentMethodType === paymentMethodType }), h("label", { htmlFor: paymentMethodType }, PaymentMethodLabels[paymentMethodType])));
|
|
17
|
+
})));
|
|
18
|
+
}
|
|
19
|
+
;
|
|
20
|
+
static get is() { return "justifi-payment-method-selector"; }
|
|
21
|
+
static get properties() {
|
|
22
|
+
return {
|
|
23
|
+
"paymentMethodTypes": {
|
|
24
|
+
"type": "unknown",
|
|
25
|
+
"mutable": false,
|
|
26
|
+
"complexType": {
|
|
27
|
+
"original": "PaymentMethodTypes[]",
|
|
28
|
+
"resolved": "PaymentMethodTypes[]",
|
|
29
|
+
"references": {
|
|
30
|
+
"PaymentMethodTypes": {
|
|
31
|
+
"location": "import",
|
|
32
|
+
"path": "../../api"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"required": false,
|
|
37
|
+
"optional": false,
|
|
38
|
+
"docs": {
|
|
39
|
+
"tags": [],
|
|
40
|
+
"text": ""
|
|
41
|
+
},
|
|
42
|
+
"defaultValue": "[]"
|
|
43
|
+
},
|
|
44
|
+
"selectedPaymentMethodType": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"mutable": false,
|
|
47
|
+
"complexType": {
|
|
48
|
+
"original": "PaymentMethodTypes",
|
|
49
|
+
"resolved": "PaymentMethodTypes.bankAccount | PaymentMethodTypes.card",
|
|
50
|
+
"references": {
|
|
51
|
+
"PaymentMethodTypes": {
|
|
52
|
+
"location": "import",
|
|
53
|
+
"path": "../../api"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"required": false,
|
|
58
|
+
"optional": false,
|
|
59
|
+
"docs": {
|
|
60
|
+
"tags": [],
|
|
61
|
+
"text": ""
|
|
62
|
+
},
|
|
63
|
+
"attribute": "selected-payment-method-type",
|
|
64
|
+
"reflect": false
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
static get events() {
|
|
69
|
+
return [{
|
|
70
|
+
"method": "paymentMethodSelected",
|
|
71
|
+
"name": "paymentMethodSelected",
|
|
72
|
+
"bubbles": true,
|
|
73
|
+
"cancelable": true,
|
|
74
|
+
"composed": true,
|
|
75
|
+
"docs": {
|
|
76
|
+
"tags": [],
|
|
77
|
+
"text": ""
|
|
78
|
+
},
|
|
79
|
+
"complexType": {
|
|
80
|
+
"original": "any",
|
|
81
|
+
"resolved": "any",
|
|
82
|
+
"references": {}
|
|
83
|
+
}
|
|
84
|
+
}];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -6,6 +6,7 @@ export class PaymentMethodForm {
|
|
|
6
6
|
this.paymentMethodFormType = undefined;
|
|
7
7
|
this.paymentMethodFormValidationStrategy = undefined;
|
|
8
8
|
this.paymentMethodStyleOverrides = undefined;
|
|
9
|
+
this.iframeOrigin = undefined;
|
|
9
10
|
this.height = 55;
|
|
10
11
|
}
|
|
11
12
|
connectedCallback() {
|
|
@@ -67,7 +68,9 @@ export class PaymentMethodForm {
|
|
|
67
68
|
}
|
|
68
69
|
;
|
|
69
70
|
getIframeSrc() {
|
|
70
|
-
|
|
71
|
+
const productionIframeOrigin = 'https://js.justifi.ai/v2';
|
|
72
|
+
const iframeOrigin = this.iframeOrigin || productionIframeOrigin;
|
|
73
|
+
let iframeSrc = `${iframeOrigin}/${this.paymentMethodFormType}`;
|
|
71
74
|
if (this.paymentMethodFormValidationStrategy) {
|
|
72
75
|
iframeSrc += `?validationStrategy=${this.paymentMethodFormValidationStrategy}`;
|
|
73
76
|
}
|
|
@@ -108,7 +111,7 @@ export class PaymentMethodForm {
|
|
|
108
111
|
},
|
|
109
112
|
"paymentMethodFormValidationStrategy": {
|
|
110
113
|
"type": "string",
|
|
111
|
-
"mutable":
|
|
114
|
+
"mutable": true,
|
|
112
115
|
"complexType": {
|
|
113
116
|
"original": "'onChange' | 'onBlur' | 'onSubmit' | 'onTouched' | 'all'",
|
|
114
117
|
"resolved": "\"all\" | \"onBlur\" | \"onChange\" | \"onSubmit\" | \"onTouched\"",
|
|
@@ -142,6 +145,23 @@ export class PaymentMethodForm {
|
|
|
142
145
|
"tags": [],
|
|
143
146
|
"text": ""
|
|
144
147
|
}
|
|
148
|
+
},
|
|
149
|
+
"iframeOrigin": {
|
|
150
|
+
"type": "string",
|
|
151
|
+
"mutable": false,
|
|
152
|
+
"complexType": {
|
|
153
|
+
"original": "string",
|
|
154
|
+
"resolved": "string",
|
|
155
|
+
"references": {}
|
|
156
|
+
},
|
|
157
|
+
"required": false,
|
|
158
|
+
"optional": true,
|
|
159
|
+
"docs": {
|
|
160
|
+
"tags": [],
|
|
161
|
+
"text": ""
|
|
162
|
+
},
|
|
163
|
+
"attribute": "iframe-origin",
|
|
164
|
+
"reflect": false
|
|
145
165
|
}
|
|
146
166
|
};
|
|
147
167
|
}
|
|
@@ -15,9 +15,7 @@ export class SelectInput {
|
|
|
15
15
|
}
|
|
16
16
|
;
|
|
17
17
|
render() {
|
|
18
|
-
return (h(Host, null, h("label", null, this.label), h("select", { name: this.name, onInput: (event) => this.onInput(event) }, this.options.map((option) => {
|
|
19
|
-
return (h("option", { value: option.value }, option.label));
|
|
20
|
-
})), this.error && h("div", { style: { color: 'red' } }, this.error)));
|
|
18
|
+
return (h(Host, null, h("label", null, this.label), h("select", { name: this.name, onInput: (event) => this.onInput(event) }, this.options.map((option) => h("option", { value: option.value }, option.label))), this.error && h("div", { style: { color: 'red' } }, this.error)));
|
|
21
19
|
}
|
|
22
20
|
static get is() { return "select-input"; }
|
|
23
21
|
static get encapsulation() { return "shadow"; }
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
var CaptureStrategy;
|
|
2
|
+
(function (CaptureStrategy) {
|
|
3
|
+
CaptureStrategy["automatic"] = "automatic";
|
|
4
|
+
CaptureStrategy["manual"] = "manual";
|
|
5
|
+
})(CaptureStrategy || (CaptureStrategy = {}));
|
|
6
|
+
var PaymentMethodTypes;
|
|
7
|
+
(function (PaymentMethodTypes) {
|
|
8
|
+
PaymentMethodTypes["card"] = "card";
|
|
9
|
+
PaymentMethodTypes["bankAccount"] = "bankAccount";
|
|
10
|
+
})(PaymentMethodTypes || (PaymentMethodTypes = {}));
|
|
11
|
+
var PaymentStatuses;
|
|
12
|
+
(function (PaymentStatuses) {
|
|
13
|
+
PaymentStatuses["pending"] = "pending";
|
|
14
|
+
PaymentStatuses["authorized"] = "authorized";
|
|
15
|
+
PaymentStatuses["succeeded"] = "succeeded";
|
|
16
|
+
PaymentStatuses["failed"] = "failed";
|
|
17
|
+
PaymentStatuses["disputed"] = "disputed";
|
|
18
|
+
PaymentStatuses["fully_refunded"] = "fully_refunded";
|
|
19
|
+
PaymentStatuses["partially_refunded"] = "partially_refunded";
|
|
20
|
+
})(PaymentStatuses || (PaymentStatuses = {}));
|
|
21
|
+
var PaymentDisputedStatuses;
|
|
22
|
+
(function (PaymentDisputedStatuses) {
|
|
23
|
+
// if a dispute is 'won', we don't show a dispute status, just general status
|
|
24
|
+
PaymentDisputedStatuses["lost"] = "lost";
|
|
25
|
+
PaymentDisputedStatuses["open"] = "open";
|
|
26
|
+
})(PaymentDisputedStatuses || (PaymentDisputedStatuses = {}));
|
|
27
|
+
class Payment {
|
|
28
|
+
constructor(payment) {
|
|
29
|
+
this.id = payment.id;
|
|
30
|
+
this.account_id = payment.account_id;
|
|
31
|
+
this.amount = payment.amount;
|
|
32
|
+
this.amount_disputed = payment.amount_disputed;
|
|
33
|
+
this.amount_refundable = payment.amount_refundable;
|
|
34
|
+
this.amount_refunded = payment.amount_refunded;
|
|
35
|
+
this.balance = payment.balance;
|
|
36
|
+
this.captured = payment.captured;
|
|
37
|
+
this.capture_strategy = payment.capture_strategy;
|
|
38
|
+
this.currency = payment.currency;
|
|
39
|
+
this.description = payment.description;
|
|
40
|
+
this.disputed = payment.disputed;
|
|
41
|
+
this.disputes = payment.disputes;
|
|
42
|
+
this.error_code = payment.error_code;
|
|
43
|
+
this.error_description = payment.error_description;
|
|
44
|
+
this.fee_amount = payment.fee_amount;
|
|
45
|
+
this.is_test = payment.is_test;
|
|
46
|
+
this.metadata = payment.metadata;
|
|
47
|
+
this.payment_method = payment.payment_method;
|
|
48
|
+
this.payment_intent_id = payment.payment_intent_id;
|
|
49
|
+
this.refunded = payment.refunded;
|
|
50
|
+
this.status = payment.status;
|
|
51
|
+
this.created_at = payment.created_at;
|
|
52
|
+
this.updated_at = payment.updated_at;
|
|
53
|
+
}
|
|
54
|
+
get disputedStatus() {
|
|
55
|
+
const lost = this.disputes.some((dispute) => dispute.status === PaymentDisputedStatuses.lost);
|
|
56
|
+
// if a dispute is 'won', we don't show a dispute status, just general status
|
|
57
|
+
if (!this.disputed) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
else if (lost) {
|
|
61
|
+
return PaymentDisputedStatuses.lost;
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
return PaymentDisputedStatuses.open;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { PaymentMethodTypes as P, Payment as a };
|