udp-react-enterprise-component-library 26.5.0-beta.12 → 26.5.0-beta.13
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/.tsbuildinfo +1 -1
- package/dist/utilities/form/paymentForm/BankAccountForm.d.ts +12 -29
- package/dist/utilities/form/paymentForm/BankAccountForm.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/BankAccountForm.js +64 -78
- package/dist/utilities/form/paymentForm/BankAccountForm.js.map +1 -1
- package/dist/utilities/form/paymentForm/BankAccountForm.mjs +77 -196
- package/dist/utilities/form/paymentForm/BankAccountForm.mjs.map +1 -1
- package/dist/utilities/form/paymentForm/CashForm.d.ts +1 -1
- package/dist/utilities/form/paymentForm/CashForm.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/CashForm.js +19 -51
- package/dist/utilities/form/paymentForm/CashForm.js.map +1 -1
- package/dist/utilities/form/paymentForm/CashForm.mjs +80 -119
- package/dist/utilities/form/paymentForm/CashForm.mjs.map +1 -1
- package/dist/utilities/form/paymentForm/CreditCardForm.d.ts +10 -21
- package/dist/utilities/form/paymentForm/CreditCardForm.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/CreditCardForm.js +81 -87
- package/dist/utilities/form/paymentForm/CreditCardForm.js.map +1 -1
- package/dist/utilities/form/paymentForm/CreditCardForm.mjs +84 -195
- package/dist/utilities/form/paymentForm/CreditCardForm.mjs.map +1 -1
- package/dist/utilities/form/paymentForm/CreditCardUtils.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/CreditCardUtils.js +5 -0
- package/dist/utilities/form/paymentForm/CreditCardUtils.js.map +1 -1
- package/dist/utilities/form/paymentForm/CreditCardUtils.mjs +1 -0
- package/dist/utilities/form/paymentForm/CreditCardUtils.mjs.map +1 -1
- package/dist/utilities/form/paymentForm/HostedPaymentError.d.ts +5 -16
- package/dist/utilities/form/paymentForm/HostedPaymentError.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/HostedPaymentError.js +6 -18
- package/dist/utilities/form/paymentForm/HostedPaymentError.js.map +1 -1
- package/dist/utilities/form/paymentForm/HostedPaymentError.mjs +18 -55
- package/dist/utilities/form/paymentForm/HostedPaymentError.mjs.map +1 -1
- package/dist/utilities/form/paymentForm/NewCreditCardForm.d.ts +12 -14
- package/dist/utilities/form/paymentForm/NewCreditCardForm.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/NewCreditCardForm.js +45 -58
- package/dist/utilities/form/paymentForm/NewCreditCardForm.js.map +1 -1
- package/dist/utilities/form/paymentForm/NewCreditCardForm.mjs +185 -262
- package/dist/utilities/form/paymentForm/NewCreditCardForm.mjs.map +1 -1
- package/dist/utilities/form/paymentForm/NewECheckForm.d.ts +9 -14
- package/dist/utilities/form/paymentForm/NewECheckForm.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/NewECheckForm.js +28 -68
- package/dist/utilities/form/paymentForm/NewECheckForm.js.map +1 -1
- package/dist/utilities/form/paymentForm/NewECheckForm.mjs +184 -227
- package/dist/utilities/form/paymentForm/NewECheckForm.mjs.map +1 -1
- package/dist/utilities/form/paymentForm/PaymentBankDetails.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/PaymentBankDetails.js +4 -2
- package/dist/utilities/form/paymentForm/PaymentBankDetails.js.map +1 -1
- package/dist/utilities/form/paymentForm/PaymentCardDetail.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/PaymentCardDetail.js +4 -2
- package/dist/utilities/form/paymentForm/PaymentCardDetail.js.map +1 -1
- package/dist/utilities/form/paymentForm/PaymentForm.d.ts +67 -3
- package/dist/utilities/form/paymentForm/PaymentForm.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/PaymentForm.js +265 -246
- package/dist/utilities/form/paymentForm/PaymentForm.js.map +1 -1
- package/dist/utilities/form/paymentForm/PaymentForm.mjs +275 -296
- package/dist/utilities/form/paymentForm/PaymentForm.mjs.map +1 -1
- package/dist/utilities/form/paymentForm/usePaymentContext.d.ts +22 -0
- package/dist/utilities/form/paymentForm/usePaymentContext.d.ts.map +1 -0
- package/dist/utilities/form/paymentForm/usePaymentContext.js +117 -0
- package/dist/utilities/form/paymentForm/usePaymentContext.js.map +1 -0
- package/dist/utilities/form/paymentForm/usePaymentContext.mjs +119 -0
- package/dist/utilities/form/paymentForm/usePaymentContext.mjs.map +1 -0
- package/dist/utilities/form/paymentForm/vendorsForms/FiservForm.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/vendorsForms/FiservForm.js +22 -28
- package/dist/utilities/form/paymentForm/vendorsForms/FiservForm.js.map +1 -1
- package/dist/utilities/form/paymentForm/vendorsForms/FiservForm.mjs +37 -32
- package/dist/utilities/form/paymentForm/vendorsForms/FiservForm.mjs.map +1 -1
- package/dist/utilities/form/paymentForm/vendorsForms/ICheckForm.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/vendorsForms/ICheckForm.js +25 -27
- package/dist/utilities/form/paymentForm/vendorsForms/ICheckForm.js.map +1 -1
- package/dist/utilities/form/paymentForm/vendorsForms/ICheckForm.mjs +40 -38
- package/dist/utilities/form/paymentForm/vendorsForms/ICheckForm.mjs.map +1 -1
- package/dist/utilities/form/paymentForm/vendorsForms/PaymentusForm.d.ts.map +1 -1
- package/dist/utilities/form/paymentForm/vendorsForms/PaymentusForm.js +25 -32
- package/dist/utilities/form/paymentForm/vendorsForms/PaymentusForm.js.map +1 -1
- package/dist/utilities/form/paymentForm/vendorsForms/PaymentusForm.mjs +38 -43
- package/dist/utilities/form/paymentForm/vendorsForms/PaymentusForm.mjs.map +1 -1
- package/package.json +6 -42
- package/dist/utilities/form/paymentForm/BankIcon.mjs +0 -56
- package/dist/utilities/form/paymentForm/BankIcon.mjs.map +0 -1
- package/dist/utilities/form/paymentForm/CashIcon.mjs +0 -55
- package/dist/utilities/form/paymentForm/CashIcon.mjs.map +0 -1
- package/dist/utilities/form/paymentForm/CheckIcon.mjs +0 -62
- package/dist/utilities/form/paymentForm/CheckIcon.mjs.map +0 -1
- package/dist/utilities/form/paymentForm/CreditCardIcon.mjs +0 -85
- package/dist/utilities/form/paymentForm/CreditCardIcon.mjs.map +0 -1
- package/dist/utilities/form/paymentForm/DisableOverlay.mjs +0 -44
- package/dist/utilities/form/paymentForm/DisableOverlay.mjs.map +0 -1
- package/dist/utilities/form/paymentForm/PaymentBankDetails.mjs +0 -161
- package/dist/utilities/form/paymentForm/PaymentBankDetails.mjs.map +0 -1
- package/dist/utilities/form/paymentForm/PaymentCard.d.ts +0 -13
- package/dist/utilities/form/paymentForm/PaymentCard.d.ts.map +0 -1
- package/dist/utilities/form/paymentForm/PaymentCard.js +0 -54
- package/dist/utilities/form/paymentForm/PaymentCard.js.map +0 -1
- package/dist/utilities/form/paymentForm/PaymentCard.mjs +0 -96
- package/dist/utilities/form/paymentForm/PaymentCard.mjs.map +0 -1
- package/dist/utilities/form/paymentForm/PaymentCardDetail.mjs +0 -284
- package/dist/utilities/form/paymentForm/PaymentCardDetail.mjs.map +0 -1
- package/dist/utilities/form/paymentForm/PaymentDropdown.mjs +0 -142
- package/dist/utilities/form/paymentForm/PaymentDropdown.mjs.map +0 -1
- package/dist/utilities/form/paymentForm/TabPanel.mjs +0 -74
- package/dist/utilities/form/paymentForm/TabPanel.mjs.map +0 -1
|
@@ -1,76 +1,21 @@
|
|
|
1
1
|
import React, { useRef, useEffect, useMemo, useState, useCallback } from 'react';
|
|
2
|
-
import { makeStyles, useTheme, Tabs, Tab, CardContent, Card, LinearProgress, Badge, Tooltip, Grow } from '@material-ui/core';
|
|
3
|
-
import { Box } from '../../../UI/Box';
|
|
4
|
-
import { Typography } from '../../../UI/dataDisplay/typography/Typography';
|
|
5
|
-
import { CircularProgress } from '../../../UI/loading/CircularProgress';
|
|
6
2
|
import { Form } from '../Form';
|
|
7
3
|
import { useTranslation } from 'react-i18next';
|
|
8
|
-
import {
|
|
4
|
+
import { UdpFlexbox } from '../../../UI/fluent-web-components/UdpFlexbox';
|
|
5
|
+
import { UdpButton } from '../../../UI/fluent-web-components/UdpButton';
|
|
6
|
+
import { UdpProgressBar } from '../../../UI/fluent-web-components/UdpProgressBar';
|
|
7
|
+
import { UdpMessageBar } from '../../../UI/fluent-web-components/UdpMessageBar';
|
|
8
|
+
import { UdpRadioGroup } from '../../../UI/fluent-web-components/UdpRadioGroup';
|
|
9
|
+
import { UdpTablist } from '../../../UI/fluent-web-components/UdpTablist';
|
|
9
10
|
import { CreditCardForm } from './CreditCardForm';
|
|
10
11
|
import { BankAccountForm } from './BankAccountForm';
|
|
11
|
-
import { CreditCardIcon } from './CreditCardIcon';
|
|
12
|
-
import { BankIcon } from './BankIcon';
|
|
13
12
|
import { CashForm } from './CashForm';
|
|
14
|
-
import { CashIcon } from './CashIcon';
|
|
15
|
-
import { DisabledOverlay } from './DisableOverlay';
|
|
16
|
-
import { CheckIcon } from './CheckIcon';
|
|
17
|
-
import { LayoutUnit } from '../../../layout/LayoutUnit';
|
|
18
|
-
import { TabPanel } from './TabPanel';
|
|
19
|
-
import { useAxiosGet } from '../../useAxiosGet';
|
|
20
13
|
import { ConfigService } from '../../../configService';
|
|
21
|
-
import { stringToProps } from '../../stringUtils';
|
|
22
14
|
import { apiMutate } from '../../useAxiosMutate';
|
|
23
15
|
import { useUser } from '../../auth/useUser';
|
|
24
16
|
import { PaymentVendorFactoryEnum } from '../../../enums/paymentVendorFactoryEnum';
|
|
25
17
|
import { PaymentMethodTypeEnum } from '../../../enums/paymentMethodTypeEnum';
|
|
26
|
-
import
|
|
27
|
-
const useStyles = makeStyles((theme) => ({
|
|
28
|
-
tab: {
|
|
29
|
-
color: grey[800],
|
|
30
|
-
'&.Mui-selected': {
|
|
31
|
-
color: theme.palette.secondary.main,
|
|
32
|
-
},
|
|
33
|
-
textTransform: 'none',
|
|
34
|
-
minWidth: 115,
|
|
35
|
-
width: 115,
|
|
36
|
-
},
|
|
37
|
-
cardFullWidth: {
|
|
38
|
-
width: "100%",
|
|
39
|
-
minWidth: "100%",
|
|
40
|
-
padding: 0,
|
|
41
|
-
},
|
|
42
|
-
paddingZero: {
|
|
43
|
-
padding: 0,
|
|
44
|
-
},
|
|
45
|
-
submitControl: {
|
|
46
|
-
marginLeft: '50px',
|
|
47
|
-
},
|
|
48
|
-
buttonProgress: {
|
|
49
|
-
color: theme.palette.secondary.main,
|
|
50
|
-
position: 'absolute',
|
|
51
|
-
top: '50%',
|
|
52
|
-
left: '50%',
|
|
53
|
-
marginTop: -12,
|
|
54
|
-
marginLeft: -12,
|
|
55
|
-
},
|
|
56
|
-
dropDownPaymentsCard: {
|
|
57
|
-
padding: '20px 12px 0px 12px',
|
|
58
|
-
},
|
|
59
|
-
assetTypeLabel: {
|
|
60
|
-
top: theme.spacing(-0.7),
|
|
61
|
-
},
|
|
62
|
-
formControl: {
|
|
63
|
-
width: '100%',
|
|
64
|
-
marginTop: '-15px',
|
|
65
|
-
},
|
|
66
|
-
}));
|
|
67
|
-
/** paymentMethodIcons @type {*} */
|
|
68
|
-
const paymentMethodIcons = {
|
|
69
|
-
'Credit Card': CreditCardIcon,
|
|
70
|
-
'Cash': CashIcon,
|
|
71
|
-
'eCheck': BankIcon,
|
|
72
|
-
'Debit Card': CheckIcon,
|
|
73
|
-
};
|
|
18
|
+
import { usePaymentContext } from './usePaymentContext';
|
|
74
19
|
const DEFAULT_ACCOUNT_TYPES = [
|
|
75
20
|
{ name: 'Checking', value: 'checking' },
|
|
76
21
|
{ name: 'Savings', value: 'savings' },
|
|
@@ -81,25 +26,6 @@ const PAYMENT_METHODS = {
|
|
|
81
26
|
E_CHECK: 'echeck',
|
|
82
27
|
DEBIT_CARD: 'debit card'
|
|
83
28
|
};
|
|
84
|
-
/**
|
|
85
|
-
* getPaymentMethodIcon
|
|
86
|
-
*
|
|
87
|
-
* @param {string} paymentMethodName
|
|
88
|
-
* @param {boolean} isSelected
|
|
89
|
-
* @param {boolean} isEnabled
|
|
90
|
-
* @param {*} theme
|
|
91
|
-
* @return {*}
|
|
92
|
-
*/
|
|
93
|
-
const getPaymentMethodIcon = (paymentMethodName, isSelected, isEnabled, theme) => {
|
|
94
|
-
// Determine the icon color based on the selection and enablement status
|
|
95
|
-
const color = isEnabled ? (isSelected ? theme.palette.secondary.main : grey[800]) : grey[400];
|
|
96
|
-
// Find the corresponding icon component from the mapping
|
|
97
|
-
const IconComponent = paymentMethodIcons[paymentMethodName];
|
|
98
|
-
// Return null if no matching icon is found (unknown payment method)
|
|
99
|
-
if (!IconComponent)
|
|
100
|
-
return null;
|
|
101
|
-
return (React.createElement(Badge, { color: "secondary", badgeContent: !isEnabled ? "!" : null }, React.createElement(IconComponent, { color: color })));
|
|
102
|
-
};
|
|
103
29
|
/**
|
|
104
30
|
* PaymentForm Component
|
|
105
31
|
*
|
|
@@ -156,44 +82,60 @@ const getPaymentMethodIcon = (paymentMethodName, isSelected, isEnabled, theme) =
|
|
|
156
82
|
* This component should be used within a React environment that supports hooks and functional components.
|
|
157
83
|
* It relies on Material-UI for UI components and theming.
|
|
158
84
|
*/
|
|
159
|
-
export const PaymentForm = ({ id, activeTab = 0, externalId,
|
|
160
|
-
|
|
161
|
-
|
|
85
|
+
export const PaymentForm = ({ id, activeTab = 0, externalId,
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
87
|
+
paymentAccounts, paymentDetails, bankAccountTypes = DEFAULT_ACCOUNT_TYPES, loading, presetDataRequest, onTabChange, onFormStatusChange, onSubmitCompleted, submit, children, childrenPosition = "before", actionLabel, render, showSandboxBanner = true, s2sToken, s2sTenantId, refreshS2sToken, allowSavePaymentMethod = true, methodPicker = 'radio', actionsStart, onSubmittingChange, onReadyChange, }) => {
|
|
88
|
+
var _a;
|
|
162
89
|
const user = useUser();
|
|
163
90
|
const { t } = useTranslation();
|
|
164
91
|
const [value, setValue] = useState(activeTab);
|
|
165
92
|
const formRef = useRef(null);
|
|
93
|
+
const methodBoxRef = useRef(null);
|
|
94
|
+
const methodBoxReleaseTimer = useRef(null);
|
|
95
|
+
/**
|
|
96
|
+
* Freeze the method-form area's current height while switching methods.
|
|
97
|
+
* The outgoing form unmounts synchronously but the incoming form's web
|
|
98
|
+
* components hydrate asynchronously, so the area collapses to ~zero height
|
|
99
|
+
* for a few frames. Inside a scroll container that collapse clamps the
|
|
100
|
+
* scroll position (the page appears to jump to the top). Holding the
|
|
101
|
+
* previous height through the swap keeps the scroll position stable.
|
|
102
|
+
*/
|
|
103
|
+
const freezeMethodBoxHeight = () => {
|
|
104
|
+
const box = methodBoxRef.current;
|
|
105
|
+
if (!box)
|
|
106
|
+
return;
|
|
107
|
+
box.style.minHeight = `${box.offsetHeight}px`;
|
|
108
|
+
if (methodBoxReleaseTimer.current) {
|
|
109
|
+
window.clearTimeout(methodBoxReleaseTimer.current);
|
|
110
|
+
}
|
|
111
|
+
methodBoxReleaseTimer.current = window.setTimeout(() => {
|
|
112
|
+
box.style.minHeight = '';
|
|
113
|
+
methodBoxReleaseTimer.current = null;
|
|
114
|
+
}, 400);
|
|
115
|
+
};
|
|
116
|
+
useEffect(() => () => {
|
|
117
|
+
if (methodBoxReleaseTimer.current) {
|
|
118
|
+
window.clearTimeout(methodBoxReleaseTimer.current);
|
|
119
|
+
}
|
|
120
|
+
}, []);
|
|
121
|
+
// Submit-path calls read the token through this ref so refreshS2sToken can
|
|
122
|
+
// swap in a fresh one mid-submit without waiting for a re-render.
|
|
123
|
+
const s2sTokenRef = useRef(s2sToken);
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
s2sTokenRef.current = s2sToken;
|
|
126
|
+
}, [s2sToken]);
|
|
166
127
|
const [paymentFormStatus, setPaymentFormStatus] = useState(null);
|
|
167
|
-
const [
|
|
168
|
-
const [selectedHostedPayment, setSelectedHostedPayment] = useState(null);
|
|
128
|
+
const [, setSelectedHostedPayment] = useState(null);
|
|
169
129
|
const [selectedPaymentType, setSelectedPaymentType] = useState(PaymentMethodTypeEnum.CreditCard);
|
|
170
130
|
const [loadingProcessPayment, setLoadingProcessPayment] = useState(false);
|
|
171
131
|
const [selectedPaymentAccount, setSelectedPaymentAccount] = useState(null);
|
|
172
132
|
// #region [API Calls]
|
|
173
133
|
/**
|
|
174
|
-
*
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* API call to get the payment method information and determine if the payment method is enabled or not
|
|
179
|
-
*
|
|
180
|
-
* @param {*} paymentMethodID : Credit card: 4001, Bank account: 4002, eCheck: 4004
|
|
181
|
-
* @return {*}
|
|
134
|
+
* Discovery: resolved list of payment methods + vendor/hosted-page info.
|
|
135
|
+
* When the backend ships a single payment-context endpoint, replace the
|
|
136
|
+
* usePaymentContext implementation — no other change in this file is needed.
|
|
182
137
|
*/
|
|
183
|
-
const
|
|
184
|
-
if (!paymentMethodID || !(user === null || user === void 0 ? void 0 : user.currentTenantId)) {
|
|
185
|
-
return;
|
|
186
|
-
}
|
|
187
|
-
try {
|
|
188
|
-
const result = await apiMutate(ConfigService.pgV1ApiUrl, `AppPaymentVendor/PaymentMethod/${paymentMethodID}`, {
|
|
189
|
-
method: 'GET',
|
|
190
|
-
}, {});
|
|
191
|
-
return result;
|
|
192
|
-
}
|
|
193
|
-
catch (error) {
|
|
194
|
-
throw new Error(`Error getting payment method info: ${error === null || error === void 0 ? void 0 : error.message}`);
|
|
195
|
-
}
|
|
196
|
-
}, [user]);
|
|
138
|
+
const { methods: paymentMethodsArray, isLoading: loadingPaymentMethods } = usePaymentContext(s2sToken, s2sTenantId);
|
|
197
139
|
/**
|
|
198
140
|
* API call to fetchPaymentMethod
|
|
199
141
|
*
|
|
@@ -205,10 +147,15 @@ export const PaymentForm = ({ id, activeTab = 0, externalId, paymentAccounts, pa
|
|
|
205
147
|
if (!currentTenantID || !paymentMethodId) {
|
|
206
148
|
return null;
|
|
207
149
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
150
|
+
const token = s2sTokenRef.current;
|
|
151
|
+
const path = token
|
|
152
|
+
? `AppPaymentVendor/PaymentMethod/${paymentMethodId}/S2S`
|
|
153
|
+
: `AppPaymentVendor/PaymentMethod/${paymentMethodId}`;
|
|
154
|
+
const config = token
|
|
155
|
+
? { method: 'GET', headers: { Authorization: `Bearer ${token}`, currentTenantId: s2sTenantId } }
|
|
156
|
+
: { method: 'GET' };
|
|
157
|
+
return apiMutate(ConfigService.pgV1ApiUrl, path, config, {});
|
|
158
|
+
}, [s2sTenantId]);
|
|
212
159
|
/**
|
|
213
160
|
* fetchPaymentMethodDetails
|
|
214
161
|
*
|
|
@@ -235,11 +182,16 @@ export const PaymentForm = ({ id, activeTab = 0, externalId, paymentAccounts, pa
|
|
|
235
182
|
if (!paymentType || !requestBody) {
|
|
236
183
|
return null;
|
|
237
184
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
185
|
+
const token = s2sTokenRef.current;
|
|
186
|
+
const path = token
|
|
187
|
+
? `ProcessPayment/${paymentType}/S2S`
|
|
188
|
+
: `ProcessPayment/${paymentType}`;
|
|
189
|
+
const body = requestBody;
|
|
190
|
+
const config = token
|
|
191
|
+
? { method: 'POST', data: body, headers: { Authorization: `Bearer ${token}`, currentTenantId: s2sTenantId } }
|
|
192
|
+
: { method: 'POST', data: body };
|
|
193
|
+
return apiMutate(ConfigService.pgV1ApiUrl, path, config, {});
|
|
194
|
+
}, [s2sTenantId]);
|
|
243
195
|
/**
|
|
244
196
|
* executeHostedPaymentPG
|
|
245
197
|
*
|
|
@@ -251,14 +203,16 @@ export const PaymentForm = ({ id, activeTab = 0, externalId, paymentAccounts, pa
|
|
|
251
203
|
if (!paymentType || !requestBody) {
|
|
252
204
|
return null;
|
|
253
205
|
}
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
206
|
+
const body = requestBody;
|
|
207
|
+
const token = s2sTokenRef.current;
|
|
208
|
+
const basePath = (requestBody === null || requestBody === void 0 ? void 0 : requestBody.paymentTokenId)
|
|
209
|
+
? `ProcessPayment/${paymentType}Profile`
|
|
210
|
+
: `ProcessHostedPaymentPagePayment/${paymentType}`;
|
|
211
|
+
const path = token ? `${basePath}/S2S` : basePath;
|
|
212
|
+
return apiMutate(ConfigService.pgV1ApiUrl, path, token
|
|
213
|
+
? { method: 'POST', data: body, headers: { Authorization: `Bearer ${token}`, currentTenantId: s2sTenantId } }
|
|
214
|
+
: { method: 'POST', data: body }, {});
|
|
215
|
+
}, [s2sTenantId]);
|
|
262
216
|
// #endregion
|
|
263
217
|
// #region [Methods]
|
|
264
218
|
const paymentMethodLabels = useMemo(() => ({
|
|
@@ -274,46 +228,80 @@ export const PaymentForm = ({ id, activeTab = 0, externalId, paymentAccounts, pa
|
|
|
274
228
|
* @param {React.ChangeEvent<{}>} event
|
|
275
229
|
* @param {number} newValue
|
|
276
230
|
*/
|
|
231
|
+
/**
|
|
232
|
+
* Update the active method by index into the enabled list.
|
|
233
|
+
* `event` is forwarded to `onTabChange` for back-compat with consumers that
|
|
234
|
+
* expected the legacy MUI tab-change signature.
|
|
235
|
+
*/
|
|
277
236
|
const handleChange = (event, newValue) => {
|
|
278
237
|
var _a;
|
|
279
|
-
|
|
238
|
+
freezeMethodBoxHeight();
|
|
280
239
|
setValue(newValue);
|
|
281
|
-
const selectedPaymentMethod =
|
|
282
|
-
// Set selected payment method and hosted payment type
|
|
240
|
+
const selectedPaymentMethod = enabledMethods === null || enabledMethods === void 0 ? void 0 : enabledMethods[newValue];
|
|
283
241
|
setSelectedHostedPayment((_a = selectedPaymentMethod === null || selectedPaymentMethod === void 0 ? void 0 : selectedPaymentMethod.paymentVendorConnection) === null || _a === void 0 ? void 0 : _a.paymentVendorFactoryID);
|
|
284
242
|
setSelectedPaymentType(selectedPaymentMethod === null || selectedPaymentMethod === void 0 ? void 0 : selectedPaymentMethod.paymentMethodID);
|
|
285
243
|
onTabChange(event, selectedPaymentMethod);
|
|
286
244
|
};
|
|
245
|
+
// onFormStatusChange is fired by the useEffect on `paymentFormStatus` below;
|
|
246
|
+
// do NOT also call it here or consumers receive the same status twice per change.
|
|
287
247
|
const handleStatusChange = (paymentFormStatus) => {
|
|
288
248
|
setPaymentFormStatus(paymentFormStatus);
|
|
289
|
-
onFormStatusChange === null || onFormStatusChange === void 0 ? void 0 : onFormStatusChange(paymentFormStatus);
|
|
290
249
|
};
|
|
291
250
|
/**
|
|
292
|
-
*
|
|
293
|
-
*
|
|
251
|
+
* Render the form for the currently-selected method. The picker only ever
|
|
252
|
+
* surfaces enabled methods, so no disabled-overlay branch is needed.
|
|
294
253
|
*
|
|
295
|
-
* @param
|
|
296
|
-
* @
|
|
254
|
+
* @param method the active payment method
|
|
255
|
+
* @param isFormDisabled when true, locks every input in the rendered form.
|
|
256
|
+
* Driven by RFF `submitting` + our own
|
|
257
|
+
* `loadingProcessPayment` so the user can't change
|
|
258
|
+
* values mid-submit.
|
|
297
259
|
*/
|
|
298
|
-
const renderPaymentMethodForm = useCallback((method) => {
|
|
299
|
-
var _a
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
260
|
+
const renderPaymentMethodForm = useCallback((method, isFormDisabled) => {
|
|
261
|
+
var _a;
|
|
262
|
+
const name = (_a = method === null || method === void 0 ? void 0 : method.name) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
263
|
+
if (name === PAYMENT_METHODS.CREDIT_CARD) {
|
|
264
|
+
return (React.createElement(CreditCardForm, Object.assign({ onStatusChange: handleStatusChange, paymentDetails: paymentDetails, externalId: externalId !== undefined ? String(externalId) : undefined, setSelectedPaymentAccount: setSelectedPaymentAccount, actionLabel: actionLabel, isFormDisabled: isFormDisabled, allowSaveMethod: allowSavePaymentMethod }, method)));
|
|
265
|
+
}
|
|
266
|
+
if (name === PAYMENT_METHODS.CASH) {
|
|
267
|
+
return (React.createElement(CashForm, Object.assign({ onStatusChange: handleStatusChange, paymentDetails: paymentDetails, isFormDisabled: isFormDisabled }, method)));
|
|
268
|
+
}
|
|
269
|
+
if (name === PAYMENT_METHODS.E_CHECK) {
|
|
270
|
+
return (React.createElement(BankAccountForm, Object.assign({ bankAccountTypes: bankAccountTypes, onStatusChange: handleStatusChange, paymentDetails: paymentDetails, externalId: externalId !== undefined ? String(externalId) : undefined, setSelectedPaymentAccount: setSelectedPaymentAccount, actionLabel: actionLabel, isFormDisabled: isFormDisabled, allowSaveMethod: allowSavePaymentMethod }, method)));
|
|
271
|
+
}
|
|
272
|
+
if (name === PAYMENT_METHODS.DEBIT_CARD) {
|
|
273
|
+
// TODO: Implement Debit Card form. Falls back to CreditCardForm until then.
|
|
274
|
+
return (React.createElement(CreditCardForm, Object.assign({ onStatusChange: handleStatusChange, paymentDetails: paymentDetails, isFormDisabled: isFormDisabled, allowSaveMethod: allowSavePaymentMethod }, method)));
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
}, [paymentDetails, bankAccountTypes, externalId, actionLabel, allowSavePaymentMethod]);
|
|
304
278
|
/**
|
|
305
|
-
*
|
|
306
|
-
*
|
|
307
|
-
*
|
|
279
|
+
* Enabled (configured) methods only. Unconfigured methods are hidden from the
|
|
280
|
+
* picker entirely — today's behaviour of "show a disabled tab with a !
|
|
281
|
+
* badge" was confusing and inaccessible.
|
|
282
|
+
*/
|
|
283
|
+
const enabledMethods = useMemo(() => {
|
|
284
|
+
var _a;
|
|
285
|
+
return (_a = paymentMethodsArray === null || paymentMethodsArray === void 0 ? void 0 : paymentMethodsArray.filter((m) => m.enabled)) !== null && _a !== void 0 ? _a : [];
|
|
286
|
+
}, [paymentMethodsArray]);
|
|
287
|
+
const activeMethod = (_a = enabledMethods[value]) !== null && _a !== void 0 ? _a : enabledMethods[0];
|
|
288
|
+
/**
|
|
289
|
+
* Sandbox mode for the currently-selected method's vendor connection.
|
|
308
290
|
*/
|
|
309
291
|
const isSandBoxMode = useMemo(() => {
|
|
310
|
-
var _a
|
|
311
|
-
const isLiveMode = (
|
|
312
|
-
|
|
313
|
-
|
|
292
|
+
var _a;
|
|
293
|
+
const isLiveMode = (_a = activeMethod === null || activeMethod === void 0 ? void 0 : activeMethod.paymentVendorConnection) === null || _a === void 0 ? void 0 : _a.isLiveMode;
|
|
294
|
+
return isLiveMode === false;
|
|
295
|
+
}, [activeMethod]);
|
|
296
|
+
// Clamp `value` if the enabled-methods list shrinks (e.g. discovery
|
|
297
|
+
// returned fewer methods than expected).
|
|
298
|
+
useEffect(() => {
|
|
299
|
+
if (enabledMethods.length === 0)
|
|
300
|
+
return;
|
|
301
|
+
if (value >= enabledMethods.length) {
|
|
302
|
+
setValue(0);
|
|
314
303
|
}
|
|
315
|
-
|
|
316
|
-
}, [paymentMethodsArray, value]);
|
|
304
|
+
}, [enabledMethods.length, value]);
|
|
317
305
|
/**
|
|
318
306
|
* getPaymentMethodLabel
|
|
319
307
|
*
|
|
@@ -326,64 +314,6 @@ export const PaymentForm = ({ id, activeTab = 0, externalId, paymentAccounts, pa
|
|
|
326
314
|
const methodLabel = (paymentMethodLabels === null || paymentMethodLabels === void 0 ? void 0 : paymentMethodLabels[normalizedMethodName]) || method.name;
|
|
327
315
|
return methodLabel;
|
|
328
316
|
};
|
|
329
|
-
/**
|
|
330
|
-
* setPaymentMethodsEnabled
|
|
331
|
-
* take every paymentMethod (eCheck, credit card, etc) and verify if the payment methods are enabled or not
|
|
332
|
-
* @return {*}
|
|
333
|
-
*/
|
|
334
|
-
const setPaymentMethodsEnabled = useCallback(async () => {
|
|
335
|
-
var _a;
|
|
336
|
-
// Filter out any falsy paymentMethod values first
|
|
337
|
-
const validPaymentMethods = paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.filter(Boolean);
|
|
338
|
-
// Use Promise.allSettled to handle both fulfilled and rejected promises
|
|
339
|
-
const results = await Promise.allSettled(validPaymentMethods === null || validPaymentMethods === void 0 ? void 0 : validPaymentMethods.map(async (paymentMethod) => {
|
|
340
|
-
var _a;
|
|
341
|
-
try {
|
|
342
|
-
const paymentMethodEnable = await getPaymentMethodInfo(paymentMethod.paymentMethodID);
|
|
343
|
-
const paymentVendorConnection = ((_a = paymentMethodEnable === null || paymentMethodEnable === void 0 ? void 0 : paymentMethodEnable.data) === null || _a === void 0 ? void 0 : _a.paymentVendorConnection) || null;
|
|
344
|
-
const providerType = paymentVendorConnection === null || paymentVendorConnection === void 0 ? void 0 : paymentVendorConnection.paymentVendorFactoryID;
|
|
345
|
-
const hostedPaymentPageSetup = (paymentVendorConnection === null || paymentVendorConnection === void 0 ? void 0 : paymentVendorConnection.hostedPaymentPageSetup.find((x) => x.useHostedPaymentPage)) || null;
|
|
346
|
-
const isHostedPaymentPage = (hostedPaymentPageSetup === null || hostedPaymentPageSetup === void 0 ? void 0 : hostedPaymentPageSetup.useHostedPaymentPage) || false;
|
|
347
|
-
let providerProps = {};
|
|
348
|
-
let hasReadPropertiesError = false;
|
|
349
|
-
let readPropertiesMessageError = null;
|
|
350
|
-
if (isHostedPaymentPage) {
|
|
351
|
-
const { error, attributes } = stringToProps(hostedPaymentPageSetup === null || hostedPaymentPageSetup === void 0 ? void 0 : hostedPaymentPageSetup.hostedPaymentPageConfig);
|
|
352
|
-
providerProps = Object.assign({ customCss: hostedPaymentPageSetup === null || hostedPaymentPageSetup === void 0 ? void 0 : hostedPaymentPageSetup.customCSS, attributes }, ((attributes === null || attributes === void 0 ? void 0 : attributes.baseUrl)
|
|
353
|
-
? { baseUrl: attributes === null || attributes === void 0 ? void 0 : attributes.baseUrl }
|
|
354
|
-
: null));
|
|
355
|
-
hasReadPropertiesError = error ? true : false;
|
|
356
|
-
readPropertiesMessageError = error;
|
|
357
|
-
}
|
|
358
|
-
// Initialize returnObject with common properties
|
|
359
|
-
let returnObject = {
|
|
360
|
-
paymentMethodID: paymentMethod.paymentMethodID,
|
|
361
|
-
name: paymentMethod.name,
|
|
362
|
-
enabled: (paymentMethodEnable === null || paymentMethodEnable === void 0 ? void 0 : paymentMethodEnable.status) === 200,
|
|
363
|
-
data: (paymentMethodEnable === null || paymentMethodEnable === void 0 ? void 0 : paymentMethodEnable.status) === 200
|
|
364
|
-
? paymentMethodEnable.data
|
|
365
|
-
: null,
|
|
366
|
-
paymentVendorConnection,
|
|
367
|
-
isHostedPaymentPage,
|
|
368
|
-
providerType,
|
|
369
|
-
providerProps,
|
|
370
|
-
hasReadPropertiesError,
|
|
371
|
-
readPropertiesMessageError,
|
|
372
|
-
};
|
|
373
|
-
return returnObject;
|
|
374
|
-
}
|
|
375
|
-
catch (error) {
|
|
376
|
-
console.error(`Error fetching payment method info for ${paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.paymentMethodID}:`, error);
|
|
377
|
-
return null;
|
|
378
|
-
}
|
|
379
|
-
}));
|
|
380
|
-
// Filter out null results in case of errors
|
|
381
|
-
const filteredResults = results
|
|
382
|
-
.filter(result => result.status === 'fulfilled' && result.value !== null)
|
|
383
|
-
.map((result) => result.value) || null;
|
|
384
|
-
setPaymentMethodsArray(filteredResults);
|
|
385
|
-
setSelectedHostedPayment(((_a = filteredResults === null || filteredResults === void 0 ? void 0 : filteredResults.find((x) => x.enabled)) === null || _a === void 0 ? void 0 : _a.providerType) || null);
|
|
386
|
-
}, [paymentMethods]);
|
|
387
317
|
/**
|
|
388
318
|
* createHostedPaymentRequest
|
|
389
319
|
*
|
|
@@ -517,28 +447,85 @@ export const PaymentForm = ({ id, activeTab = 0, externalId, paymentAccounts, pa
|
|
|
517
447
|
*/
|
|
518
448
|
const submitPaymentForm = useCallback(async (formData) => {
|
|
519
449
|
var _a, _b, _c;
|
|
450
|
+
var _d;
|
|
520
451
|
if (!formData)
|
|
521
452
|
return;
|
|
453
|
+
// Discovery still in flight or returned no payable methods — no method
|
|
454
|
+
// fields are mounted yet, so nothing validated and formData is empty.
|
|
455
|
+
// The internal button is disabled in this window, but external
|
|
456
|
+
// form-registry submit buttons can still land here.
|
|
457
|
+
if (loadingPaymentMethods || enabledMethods.length === 0)
|
|
458
|
+
return;
|
|
522
459
|
setLoadingProcessPayment(true);
|
|
523
|
-
|
|
460
|
+
// Payment-link tokens can expire between page load and submit; re-mint
|
|
461
|
+
// when the host provides a way to. Failure keeps the existing token.
|
|
462
|
+
if (refreshS2sToken) {
|
|
463
|
+
try {
|
|
464
|
+
const freshToken = await refreshS2sToken();
|
|
465
|
+
if (freshToken) {
|
|
466
|
+
s2sTokenRef.current = freshToken;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
catch (error) {
|
|
470
|
+
console.warn('refreshS2sToken failed; submitting with the existing token', error);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
// Reactive backstop to the proactive refresh above: when a call is
|
|
474
|
+
// rejected with a 403 (how the Payment Portal reports an expired S2S
|
|
475
|
+
// token), re-mint the token and re-issue that call once. Never retries
|
|
476
|
+
// other statuses — a 500 from ProcessPayment is a real error and may
|
|
477
|
+
// mean the charge already went through.
|
|
478
|
+
const retryOnAuthError = async (call) => {
|
|
479
|
+
var _a;
|
|
480
|
+
try {
|
|
481
|
+
return await call();
|
|
482
|
+
}
|
|
483
|
+
catch (error) {
|
|
484
|
+
if (!refreshS2sToken || ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status) !== 403)
|
|
485
|
+
throw error;
|
|
486
|
+
let freshToken;
|
|
487
|
+
try {
|
|
488
|
+
freshToken = await refreshS2sToken();
|
|
489
|
+
}
|
|
490
|
+
catch (_b) {
|
|
491
|
+
throw error;
|
|
492
|
+
}
|
|
493
|
+
if (!freshToken)
|
|
494
|
+
throw error;
|
|
495
|
+
s2sTokenRef.current = freshToken;
|
|
496
|
+
return call();
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
const currentTenantID = s2sTokenRef.current ? s2sTenantId : user === null || user === void 0 ? void 0 : user.currentTenantId;
|
|
524
500
|
const paymentMethodId = selectedPaymentType;
|
|
525
501
|
if (!currentTenantID || !paymentMethodId) {
|
|
526
|
-
onSubmitCompleted === null || onSubmitCompleted === void 0 ? void 0 : onSubmitCompleted(null, {
|
|
502
|
+
onSubmitCompleted === null || onSubmitCompleted === void 0 ? void 0 : onSubmitCompleted(null, {
|
|
503
|
+
error: true,
|
|
504
|
+
message: 'Missing tenant ID or payment method ID',
|
|
505
|
+
});
|
|
506
|
+
setLoadingProcessPayment(false);
|
|
507
|
+
return;
|
|
527
508
|
}
|
|
528
509
|
try {
|
|
529
|
-
const paymentMethod = await fetchPaymentMethodDetails(currentTenantID, paymentMethodId);
|
|
510
|
+
const paymentMethod = await retryOnAuthError(() => fetchPaymentMethodDetails(currentTenantID, paymentMethodId));
|
|
530
511
|
const isHostedPayment = ((_c = (_b = (_a = paymentMethod.paymentVendorConnection) === null || _a === void 0 ? void 0 : _a.hostedPaymentPageSetup) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.useHostedPaymentPage) || false;
|
|
531
512
|
const dataRequest = createDataRequest(formData, paymentMethod, isHostedPayment, paymentMethodId, selectedPaymentAccount);
|
|
532
|
-
const paymentResult = await executePayment(paymentMethodId, dataRequest, isHostedPayment);
|
|
513
|
+
const paymentResult = await retryOnAuthError(() => executePayment(paymentMethodId, dataRequest, isHostedPayment));
|
|
533
514
|
onSubmitCompleted === null || onSubmitCompleted === void 0 ? void 0 : onSubmitCompleted(formData, paymentResult);
|
|
534
515
|
}
|
|
535
516
|
catch (error) {
|
|
536
|
-
|
|
517
|
+
// Route failures through onSubmitCompleted so consumers can react
|
|
518
|
+
// (previous behaviour threw from an async event handler -> unhandled rejection).
|
|
519
|
+
console.error('Error processing payment:', error);
|
|
520
|
+
onSubmitCompleted === null || onSubmitCompleted === void 0 ? void 0 : onSubmitCompleted(formData, {
|
|
521
|
+
error: true,
|
|
522
|
+
message: (_d = error === null || error === void 0 ? void 0 : error.message) !== null && _d !== void 0 ? _d : 'Error processing payment',
|
|
523
|
+
});
|
|
537
524
|
}
|
|
538
525
|
finally {
|
|
539
526
|
setLoadingProcessPayment(false);
|
|
540
527
|
}
|
|
541
|
-
}, [
|
|
528
|
+
}, [createDataRequest, selectedPaymentType, user, selectedPaymentAccount, s2sTenantId, refreshS2sToken, executePayment, fetchPaymentMethodDetails, onSubmitCompleted, loadingPaymentMethods, enabledMethods]);
|
|
542
529
|
/**
|
|
543
530
|
* Handles the form submission for iCheck payments.
|
|
544
531
|
*
|
|
@@ -548,51 +535,83 @@ export const PaymentForm = ({ id, activeTab = 0, externalId, paymentAccounts, pa
|
|
|
548
535
|
*
|
|
549
536
|
*/
|
|
550
537
|
const handleICheckPaymentFormStatus = useCallback(() => {
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
538
|
+
const vendor = paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.selectedHostedPayment;
|
|
539
|
+
const isAutoSubmitVendor = vendor === PaymentVendorFactoryEnum.ICheck ||
|
|
540
|
+
vendor === PaymentVendorFactoryEnum.Paymentus;
|
|
541
|
+
if (isAutoSubmitVendor && (formRef === null || formRef === void 0 ? void 0 : formRef.current)) {
|
|
542
|
+
formRef.current.submit();
|
|
555
543
|
}
|
|
556
544
|
}, [paymentFormStatus]);
|
|
557
545
|
// #endregion
|
|
558
546
|
// #region [Effects]
|
|
547
|
+
// Default the selected vendor to the first enabled method once discovery
|
|
548
|
+
// completes. Matches the previous behaviour from setPaymentMethodsEnabled.
|
|
559
549
|
useEffect(() => {
|
|
560
|
-
|
|
561
|
-
|
|
550
|
+
var _a;
|
|
551
|
+
if (!paymentMethodsArray)
|
|
552
|
+
return;
|
|
553
|
+
const firstEnabled = paymentMethodsArray.find((m) => m.enabled);
|
|
554
|
+
setSelectedHostedPayment((_a = firstEnabled === null || firstEnabled === void 0 ? void 0 : firstEnabled.providerType) !== null && _a !== void 0 ? _a : null);
|
|
555
|
+
}, [paymentMethodsArray]);
|
|
562
556
|
useEffect(() => {
|
|
563
557
|
onFormStatusChange === null || onFormStatusChange === void 0 ? void 0 : onFormStatusChange(paymentFormStatus);
|
|
564
558
|
handleICheckPaymentFormStatus();
|
|
565
559
|
}, [paymentFormStatus]);
|
|
560
|
+
// onSubmittingChange is intentionally omitted from deps; consumers may pass
|
|
561
|
+
// unstable references and we only want to fire when the window changes.
|
|
562
|
+
useEffect(() => {
|
|
563
|
+
onSubmittingChange === null || onSubmittingChange === void 0 ? void 0 : onSubmittingChange(loadingProcessPayment);
|
|
564
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
565
|
+
}, [loadingProcessPayment]);
|
|
566
|
+
// Mirrors the internal submit button's disabled conditions so hosts with
|
|
567
|
+
// external submit buttons can gate them identically. Callback omitted from
|
|
568
|
+
// deps for the same unstable-reference reason as above.
|
|
569
|
+
const isReadyToSubmit = !loadingPaymentMethods &&
|
|
570
|
+
enabledMethods.length > 0 &&
|
|
571
|
+
(paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.isValid) !== false;
|
|
572
|
+
useEffect(() => {
|
|
573
|
+
onReadyChange === null || onReadyChange === void 0 ? void 0 : onReadyChange(isReadyToSubmit);
|
|
574
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
575
|
+
}, [isReadyToSubmit]);
|
|
566
576
|
// #endregion
|
|
567
|
-
return (React.createElement(React.Fragment, null,
|
|
568
|
-
|
|
569
|
-
top: 0,
|
|
570
|
-
left: 0,
|
|
571
|
-
width: '100%',
|
|
572
|
-
height: '100%',
|
|
573
|
-
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
|
574
|
-
zIndex: 9999,
|
|
575
|
-
display: 'flex',
|
|
576
|
-
alignItems: 'center',
|
|
577
|
-
justifyContent: 'center',
|
|
578
|
-
} }, React.createElement(CircularProgress, { size: "3rem", color: "primary" }))), React.createElement(Form, { id: id, onSubmit: submitPaymentForm, autocomplete: "off", render: (params) => {
|
|
577
|
+
return (React.createElement(React.Fragment, null, React.createElement(Form, { id: id, onSubmit: submitPaymentForm, render: (params) => {
|
|
578
|
+
var _a, _b;
|
|
579
579
|
formRef.current = params === null || params === void 0 ? void 0 : params.form;
|
|
580
|
-
|
|
581
|
-
//
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
580
|
+
const hasMultipleMethods = enabledMethods.length > 1;
|
|
581
|
+
// Discovery has completed and there are no enabled methods.
|
|
582
|
+
const hasNoMethods = paymentMethodsArray !== undefined &&
|
|
583
|
+
enabledMethods.length === 0 &&
|
|
584
|
+
!loadingPaymentMethods;
|
|
585
|
+
// RFF `submitting` flips while the Promise returned from
|
|
586
|
+
// submitPaymentForm is in flight. loadingProcessPayment is our own
|
|
587
|
+
// signal for the same window. Either way, lock the UI so the user
|
|
588
|
+
// can't change values or switch methods mid-submit.
|
|
589
|
+
const isSubmitting = Boolean(params === null || params === void 0 ? void 0 : params.submitting) || loadingProcessPayment;
|
|
590
|
+
return (React.createElement(React.Fragment, null, React.createElement(UdpFlexbox, { direction: "column", gap: "md", wrap: "nowrap" }, childrenPosition === "before" && children, (loading || loadingPaymentMethods) && React.createElement(UdpProgressBar, null), hasNoMethods && (React.createElement(UdpMessageBar, { intent: "error" }, t("No payment methods are available for this account"))), showSandboxBanner && isSandBoxMode && (React.createElement(UdpMessageBar, { intent: "warning" }, t("You are currently in test mode using a Sandbox account"))), hasMultipleMethods && methodPicker === 'tabs' && (React.createElement(UdpTablist, { size: "small", disabled: isSubmitting, activeId: String((_a = activeMethod === null || activeMethod === void 0 ? void 0 : activeMethod.paymentMethodID) !== null && _a !== void 0 ? _a : ''), tabList: enabledMethods.map((m) => ({
|
|
591
|
+
id: String(m.paymentMethodID),
|
|
592
|
+
label: getPaymentMethodLabel(m),
|
|
593
|
+
})), onTabChange: (e) => {
|
|
594
|
+
const id = String(e.detail);
|
|
595
|
+
const nextIdx = enabledMethods.findIndex((m) => String(m.paymentMethodID) === id);
|
|
596
|
+
if (nextIdx >= 0) {
|
|
597
|
+
handleChange(e, nextIdx);
|
|
598
|
+
}
|
|
599
|
+
} })), hasMultipleMethods && methodPicker === 'radio' && (React.createElement(UdpRadioGroup, { label: t("Payment method"), name: "paymentMethod", disabled: isSubmitting, includeErrorPadding: false, value: String((_b = activeMethod === null || activeMethod === void 0 ? void 0 : activeMethod.paymentMethodID) !== null && _b !== void 0 ? _b : ''), items: enabledMethods.map((m) => ({
|
|
600
|
+
label: getPaymentMethodLabel(m),
|
|
601
|
+
value: String(m.paymentMethodID),
|
|
602
|
+
})), onChange: (e) => {
|
|
603
|
+
const id = e.target.value;
|
|
604
|
+
const nextIdx = enabledMethods.findIndex((m) => String(m.paymentMethodID) === id);
|
|
605
|
+
if (nextIdx >= 0) {
|
|
606
|
+
handleChange(e, nextIdx);
|
|
607
|
+
}
|
|
608
|
+
} })), React.createElement("div", { ref: methodBoxRef }, activeMethod && renderPaymentMethodForm(activeMethod, isSubmitting)), submit && (React.createElement(UdpFlexbox, { direction: "row", gap: "sm", align: "center", wrap: "nowrap" }, actionsStart, React.createElement(UdpButton, { type: "submit", form: id, appearance: "primary", loading: loading || loadingProcessPayment,
|
|
609
|
+
// Not actionable until discovery resolves a payable method
|
|
610
|
+
// (no fields mounted yet — a click would submit an empty
|
|
611
|
+
// form), nor in hosted-iframe mode until the vendor iframe
|
|
612
|
+
// reports a token (isValid). Tokenization is driven inside
|
|
613
|
+
// the iframe, so this cannot deadlock the flow.
|
|
614
|
+
disabled: loadingPaymentMethods || hasNoMethods || (paymentFormStatus === null || paymentFormStatus === void 0 ? void 0 : paymentFormStatus.isValid) === false }, actionLabel || t('Save')))), childrenPosition === "after" && children, typeof render === 'function' ? render(params) : render), childrenPosition === "outside" && children));
|
|
596
615
|
} })));
|
|
597
616
|
};
|
|
598
617
|
//# sourceMappingURL=PaymentForm.js.map
|