Add failure state to create payment hook (#191)

This commit is contained in:
Ildar Galeev 2023-05-24 19:31:44 +03:00 committed by GitHub
parent 98404b1f15
commit 50ad71282d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 165 additions and 81 deletions

View File

@ -9,12 +9,9 @@ function getFingerprintFromComponents(components: Fingerprint2.Component[]) {
} }
const getClientInfoUrl = (): { url: string } | undefined => { const getClientInfoUrl = (): { url: string } | undefined => {
const url = (document.referrer || '').slice( if (document.referrer === '') return;
0, const url = new URL(document.referrer);
// URL max length (API constraint) return { url: url.origin };
599
);
return url ? { url } : undefined;
}; };
export const createPaymentResource = ( export const createPaymentResource = (

View File

@ -4,8 +4,8 @@ import { InjectedFormProps, reduxForm } from 'redux-form';
import { FormGroup } from '../form-group'; import { FormGroup } from '../form-group';
import { CardHolder, CardNumber, ExpireDate, SecureCode } from './fields'; import { CardHolder, CardNumber, ExpireDate, SecureCode } from './fields';
import { CardFormInfo, CardFormValues, FormName, PaymentStatus } from 'checkout/state'; import { CardFormInfo, CardFormValues, FormName, PaymentStatus, ResultFormInfo, ResultType } from 'checkout/state';
import { pay, prepareToPay, setViewInfoError } from 'checkout/actions'; import { goToFormInfo, pay, prepareToPay, setViewInfoError } from 'checkout/actions';
import { PayButton } from '../pay-button'; import { PayButton } from '../pay-button';
import { Header } from '../header/header'; import { Header } from '../header/header';
import { toAmountConfig, toCardHolderConfig } from '../fields-config'; import { toAmountConfig, toCardHolderConfig } from '../fields-config';
@ -14,7 +14,6 @@ import { useAppDispatch, useAppSelector } from 'checkout/configure-store';
import { getActiveModalFormSelector } from 'checkout/selectors'; import { getActiveModalFormSelector } from 'checkout/selectors';
import { InitialContext } from '../../../../initial-context'; import { InitialContext } from '../../../../initial-context';
import { PaymentMethodName, useCreatePayment } from 'checkout/hooks'; import { PaymentMethodName, useCreatePayment } from 'checkout/hooks';
import isNil from 'checkout/utils/is-nil';
const CardFormDef = ({ submitFailed, initialize, handleSubmit }: InjectedFormProps) => { const CardFormDef = ({ submitFailed, initialize, handleSubmit }: InjectedFormProps) => {
const { const {
@ -22,7 +21,7 @@ const CardFormDef = ({ submitFailed, initialize, handleSubmit }: InjectedFormPro
initConfig, initConfig,
model: { invoiceTemplate } model: { invoiceTemplate }
} = useContext(InitialContext); } = useContext(InitialContext);
const { paymentPayload, setFormData } = useCreatePayment(); const { createPaymentState, setFormData } = useCreatePayment();
const { paymentStatus } = useAppSelector<CardFormInfo>(getActiveModalFormSelector); const { paymentStatus } = useAppSelector<CardFormInfo>(getActiveModalFormSelector);
const cardHolder = toCardHolderConfig(initConfig.requireCardHolder); const cardHolder = toCardHolderConfig(initConfig.requireCardHolder);
const amount = toAmountConfig(initConfig, invoiceTemplate); const amount = toAmountConfig(initConfig, invoiceTemplate);
@ -47,10 +46,13 @@ const CardFormDef = ({ submitFailed, initialize, handleSubmit }: InjectedFormPro
if (submitFailed) { if (submitFailed) {
dispatch(setViewInfoError(true)); dispatch(setViewInfoError(true));
} }
if (!isNil(paymentPayload)) { if (createPaymentState.status === 'SUCCESS') {
dispatch(pay(paymentPayload)); dispatch(pay(createPaymentState.data));
} }
}, [submitFailed, paymentPayload]); if (createPaymentState.status === 'FAILURE') {
dispatch(goToFormInfo(new ResultFormInfo(ResultType.hookError, createPaymentState.error)));
}
}, [submitFailed, createPaymentState]);
const submit = (values: CardFormValues) => { const submit = (values: CardFormValues) => {
dispatch(prepareToPay()); dispatch(prepareToPay());

View File

@ -6,7 +6,9 @@ import {
FormName, FormName,
PaymentTerminalFormInfo, PaymentTerminalFormInfo,
PaymentTerminalFormValues, PaymentTerminalFormValues,
PaymentTerminalSelectorFormInfo PaymentTerminalSelectorFormInfo,
ResultFormInfo,
ResultType
} from 'checkout/state'; } from 'checkout/state';
import { getMetadata, PaymentMethodItemContainer } from 'checkout/components/ui'; import { getMetadata, PaymentMethodItemContainer } from 'checkout/components/ui';
import { PaymentMethodName, ServiceProvider, ServiceProviderContactInfo } from 'checkout/backend'; import { PaymentMethodName, ServiceProvider, ServiceProviderContactInfo } from 'checkout/backend';
@ -45,7 +47,7 @@ export const PaymentTerminalMethodItem = ({ method }: PaymentTerminalMethodItemP
const emailPrefilled = !!initConfig.email; const emailPrefilled = !!initConfig.email;
const phoneNumberPrefilled = !!initConfig.phoneNumber; const phoneNumberPrefilled = !!initConfig.phoneNumber;
const { paymentPayload, setFormData } = useCreatePayment(); const { createPaymentState, setFormData } = useCreatePayment();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const onClick = () => { const onClick = () => {
@ -69,10 +71,13 @@ export const PaymentTerminalMethodItem = ({ method }: PaymentTerminalMethodItemP
}; };
useEffect(() => { useEffect(() => {
if (!isNil(paymentPayload)) { if (createPaymentState.status === 'SUCCESS') {
dispatch(pay(paymentPayload)); dispatch(pay(createPaymentState.data));
} }
}, [paymentPayload]); if (createPaymentState.status === 'FAILURE') {
dispatch(goToFormInfo(new ResultFormInfo(ResultType.hookError, createPaymentState.error)));
}
}, [createPaymentState]);
return ( return (
<PaymentMethodItemContainer id={`${Math.floor(Math.random() * 100)}-payment-method-item`} onClick={onClick}> <PaymentMethodItemContainer id={`${Math.floor(Math.random() * 100)}-payment-method-item`} onClick={onClick}>

View File

@ -2,11 +2,11 @@ import * as React from 'react';
import { useContext, useEffect } from 'react'; import { useContext, useEffect } from 'react';
import { InjectedFormProps, reduxForm } from 'redux-form'; import { InjectedFormProps, reduxForm } from 'redux-form';
import { FormName, PaymentTerminalFormValues } from 'checkout/state'; import { FormName, PaymentTerminalFormValues, ResultFormInfo, ResultType } from 'checkout/state';
import { Header } from '../header'; import { Header } from '../header';
import { useAppDispatch } from 'checkout/configure-store'; import { useAppDispatch } from 'checkout/configure-store';
import { ProviderSelectorField } from './provider-selector'; import { ProviderSelectorField } from './provider-selector';
import { pay, prepareToPay, setViewInfoError } from 'checkout/actions'; import { goToFormInfo, pay, prepareToPay, setViewInfoError } from 'checkout/actions';
import { PayButton } from '../pay-button'; import { PayButton } from '../pay-button';
import { PaymentMethodName } from 'checkout/backend'; import { PaymentMethodName } from 'checkout/backend';
import styled from 'checkout/styled-components'; import styled from 'checkout/styled-components';
@ -14,7 +14,6 @@ import { toEmailConfig, toPhoneNumberConfig } from '../fields-config';
import { FormGroup } from '../form-group'; import { FormGroup } from '../form-group';
import { Email, Phone } from '../common-fields'; import { Email, Phone } from '../common-fields';
import { getMetadata } from 'checkout/components'; import { getMetadata } from 'checkout/components';
import isNil from 'checkout/utils/is-nil';
import { InitialContext } from '../../../../initial-context'; import { InitialContext } from '../../../../initial-context';
import { getAvailableTerminalPaymentMethod } from '../get-available-terminal-payment-method'; import { getAvailableTerminalPaymentMethod } from '../get-available-terminal-payment-method';
@ -29,7 +28,7 @@ const ProviderSelectorDescription = styled.p`
export const PaymentTerminalBankCardFormDef: React.FC<InjectedFormProps> = ({ submitFailed, handleSubmit }) => { export const PaymentTerminalBankCardFormDef: React.FC<InjectedFormProps> = ({ submitFailed, handleSubmit }) => {
const { locale, initConfig, availablePaymentMethods } = useContext(InitialContext); const { locale, initConfig, availablePaymentMethods } = useContext(InitialContext);
const { paymentPayload, setFormData } = useCreatePayment(); const { createPaymentState, setFormData } = useCreatePayment();
const paymentMethod = getAvailableTerminalPaymentMethod(availablePaymentMethods, KnownProviderCategories.BankCard); const paymentMethod = getAvailableTerminalPaymentMethod(availablePaymentMethods, KnownProviderCategories.BankCard);
const serviceProviders = paymentMethod?.serviceProviders; const serviceProviders = paymentMethod?.serviceProviders;
const email = toEmailConfig(initConfig.email); const email = toEmailConfig(initConfig.email);
@ -45,10 +44,13 @@ export const PaymentTerminalBankCardFormDef: React.FC<InjectedFormProps> = ({ su
if (submitFailed) { if (submitFailed) {
dispatch(setViewInfoError(true)); dispatch(setViewInfoError(true));
} }
if (!isNil(paymentPayload)) { if (createPaymentState.status === 'SUCCESS') {
dispatch(pay(paymentPayload)); dispatch(pay(createPaymentState.data));
} }
}, [submitFailed, paymentPayload]); if (createPaymentState.status === 'FAILURE') {
dispatch(goToFormInfo(new ResultFormInfo(ResultType.hookError, createPaymentState.error)));
}
}, [submitFailed, createPaymentState]);
const submit = (values: PaymentTerminalFormValues) => { const submit = (values: PaymentTerminalFormValues) => {
dispatch(prepareToPay()); dispatch(prepareToPay());

View File

@ -5,8 +5,15 @@ import get from 'lodash-es/get';
import styled from 'checkout/styled-components'; import styled from 'checkout/styled-components';
import { useAppDispatch, useAppSelector } from 'checkout/configure-store'; import { useAppDispatch, useAppSelector } from 'checkout/configure-store';
import { pay, prepareToPay, setViewInfoError } from 'checkout/actions'; import { goToFormInfo, pay, prepareToPay, setViewInfoError } from 'checkout/actions';
import { FormName, PaymentStatus, PaymentTerminalFormValues, PaymentTerminalFormInfo } from 'checkout/state'; import {
FormName,
PaymentStatus,
PaymentTerminalFormValues,
PaymentTerminalFormInfo,
ResultFormInfo,
ResultType
} from 'checkout/state';
import { Header } from '../header'; import { Header } from '../header';
import { PayButton } from '../pay-button'; import { PayButton } from '../pay-button';
import { FormGroup } from '../form-group'; import { FormGroup } from '../form-group';
@ -26,7 +33,6 @@ import {
} from './init-config-payment'; } from './init-config-payment';
import { MetadataSelect } from './metadata-select'; import { MetadataSelect } from './metadata-select';
import { PaymentMethodName, useCreatePayment } from 'checkout/hooks'; import { PaymentMethodName, useCreatePayment } from 'checkout/hooks';
import isNil from 'checkout/utils/is-nil';
import { InitialContext } from '../../../../initial-context'; import { InitialContext } from '../../../../initial-context';
const Container = styled.div` const Container = styled.div`
@ -42,7 +48,7 @@ const PaymentTerminalFormRef: React.FC<InjectedFormProps> = ({ submitFailed, ini
initConfig, initConfig,
model: { serviceProviders, invoiceTemplate } model: { serviceProviders, invoiceTemplate }
} = useContext(InitialContext); } = useContext(InitialContext);
const { paymentPayload, setFormData } = useCreatePayment(); const { createPaymentState, setFormData } = useCreatePayment();
const { providerID, paymentStatus } = useAppSelector<PaymentTerminalFormInfo>(getActiveModalFormSelector); const { providerID, paymentStatus } = useAppSelector<PaymentTerminalFormInfo>(getActiveModalFormSelector);
const serviceProvider = serviceProviders.find((value) => value.id === providerID); const serviceProvider = serviceProviders.find((value) => value.id === providerID);
const { form, contactInfo, logo, paymentSessionInfo, prefilledMetadataValues } = getMetadata(serviceProvider); const { form, contactInfo, logo, paymentSessionInfo, prefilledMetadataValues } = getMetadata(serviceProvider);
@ -88,10 +94,13 @@ const PaymentTerminalFormRef: React.FC<InjectedFormProps> = ({ submitFailed, ini
if (submitFailed) { if (submitFailed) {
dispatch(setViewInfoError(true)); dispatch(setViewInfoError(true));
} }
if (!isNil(paymentPayload)) { if (createPaymentState.status === 'SUCCESS') {
dispatch(pay(paymentPayload)); dispatch(pay(createPaymentState.data));
} }
}, [submitFailed, paymentPayload]); if (createPaymentState.status === 'FAILURE') {
dispatch(goToFormInfo(new ResultFormInfo(ResultType.hookError, createPaymentState.error)));
}
}, [submitFailed, createPaymentState]);
const submit = (values?: Partial<PaymentTerminalFormValues>) => { const submit = (values?: Partial<PaymentTerminalFormValues>) => {
const payload = { const payload = {

View File

@ -4,6 +4,7 @@ import { ResultFormContent } from './result-form-content';
import { getFailedDescription } from './get-failed-description'; import { getFailedDescription } from './get-failed-description';
import { getLastChange } from 'checkout/utils'; import { getLastChange } from 'checkout/utils';
import { ResultFormType } from './result-form-content'; import { ResultFormType } from './result-form-content';
import isObject from 'checkout/utils/is-object';
export const refunded = (l: Locale): ResultFormContent => ({ export const refunded = (l: Locale): ResultFormContent => ({
hasActions: false, hasActions: false,
@ -34,6 +35,23 @@ export const failed = (l: Locale, e: PaymentError | LogicError): ResultFormConte
type: ResultFormType.ERROR type: ResultFormType.ERROR
}); });
const getErrorDescription = (error: unknown): string => {
if (error instanceof Error) {
return `${error.name}: ${error.message}`;
} else if (isObject(error)) {
return JSON.stringify(error);
}
return 'Unknown error';
};
export const failedHook = (l: Locale, error: unknown): ResultFormContent => ({
hasActions: true,
hasDone: false,
header: l['form.header.final.failed.label'],
description: getErrorDescription(error),
type: ResultFormType.ERROR
});
const processed = (l: Locale): ResultFormContent => ({ const processed = (l: Locale): ResultFormContent => ({
hasActions: false, hasActions: false,
hasDone: true, hasDone: true,

View File

@ -5,6 +5,7 @@ import { FormName, ModalForms, ModalName, ResultFormInfo, ResultState, ResultTyp
import { setResult } from 'checkout/actions'; import { setResult } from 'checkout/actions';
import { findNamed } from 'checkout/utils'; import { findNamed } from 'checkout/utils';
import { makeContentError, makeContentInvoice } from './make-content'; import { makeContentError, makeContentInvoice } from './make-content';
import { failedHook } from './make-content/make-from-payment-change';
import { ActionBlock } from './action-block'; import { ActionBlock } from './action-block';
import { ResultIcon } from './result-icons'; import { ResultIcon } from './result-icons';
import styled, { css } from 'checkout/styled-components'; import styled, { css } from 'checkout/styled-components';
@ -78,6 +79,8 @@ export const ResultForm = () => {
switch (resultFormInfo.resultType) { switch (resultFormInfo.resultType) {
case ResultType.error: case ResultType.error:
return makeContentError(locale, error); return makeContentError(locale, error);
case ResultType.hookError:
return failedHook(locale, resultFormInfo.hookError);
case ResultType.processed: case ResultType.processed:
return makeContentInvoice(locale, events.events, events.status, error); return makeContentInvoice(locale, events.events, events.status, error);
} }

View File

@ -4,19 +4,18 @@ import { InjectedFormProps, reduxForm } from 'redux-form';
import get from 'lodash-es/get'; import get from 'lodash-es/get';
import { FormGroup } from '../form-group'; import { FormGroup } from '../form-group';
import { FormName, PaymentStatus, WalletFormInfo, WalletFormValues } from 'checkout/state'; import { FormName, PaymentStatus, ResultFormInfo, ResultType, WalletFormInfo, WalletFormValues } from 'checkout/state';
import { PayButton } from '../pay-button'; import { PayButton } from '../pay-button';
import { Header } from '../header'; import { Header } from '../header';
import { Amount } from '../common-fields'; import { Amount } from '../common-fields';
import { toFieldsConfig } from '../fields-config'; import { toFieldsConfig } from '../fields-config';
import { pay, prepareToPay, setViewInfoError } from 'checkout/actions'; import { goToFormInfo, pay, prepareToPay, setViewInfoError } from 'checkout/actions';
import { SignUp } from './sign-up'; import { SignUp } from './sign-up';
import { getActiveModalFormSelector } from 'checkout/selectors'; import { getActiveModalFormSelector } from 'checkout/selectors';
import { useAppDispatch, useAppSelector } from 'checkout/configure-store'; import { useAppDispatch, useAppSelector } from 'checkout/configure-store';
import { getMetadata, MetadataField, MetadataLogo, obscurePassword, sortByIndex } from 'checkout/components/ui'; import { getMetadata, MetadataField, MetadataLogo, obscurePassword, sortByIndex } from 'checkout/components/ui';
import { LogoContainer } from './logo-container'; import { LogoContainer } from './logo-container';
import { PaymentMethodName, useCreatePayment } from 'checkout/hooks'; import { PaymentMethodName, useCreatePayment } from 'checkout/hooks';
import isNil from 'checkout/utils/is-nil';
import { InitialContext } from '../../../../initial-context'; import { InitialContext } from '../../../../initial-context';
@ -26,7 +25,7 @@ const WalletFormDef = ({ submitFailed, initialize, handleSubmit }: InjectedFormP
initConfig, initConfig,
model: { invoiceTemplate } model: { invoiceTemplate }
} = useContext(InitialContext); } = useContext(InitialContext);
const { paymentPayload, setFormData } = useCreatePayment(); const { createPaymentState, setFormData } = useCreatePayment();
const { activeProvider, paymentStatus } = useAppSelector<WalletFormInfo>(getActiveModalFormSelector); const { activeProvider, paymentStatus } = useAppSelector<WalletFormInfo>(getActiveModalFormSelector);
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const formValues = useAppSelector((s) => get(s.form, 'walletForm.values')); const formValues = useAppSelector((s) => get(s.form, 'walletForm.values'));
@ -60,10 +59,13 @@ const WalletFormDef = ({ submitFailed, initialize, handleSubmit }: InjectedFormP
if (submitFailed) { if (submitFailed) {
dispatch(setViewInfoError(true)); dispatch(setViewInfoError(true));
} }
if (!isNil(paymentPayload)) { if (createPaymentState.status === 'SUCCESS') {
dispatch(pay(paymentPayload)); dispatch(pay(createPaymentState.data));
} }
}, [submitFailed, paymentPayload]); if (createPaymentState.status === 'FAILURE') {
dispatch(goToFormInfo(new ResultFormInfo(ResultType.hookError, createPaymentState.error)));
}
}, [submitFailed, createPaymentState]);
return ( return (
<form id="wallet-form" onSubmit={handleSubmit(submit)}> <form id="wallet-form" onSubmit={handleSubmit(submit)}>

View File

@ -1,7 +1,14 @@
import * as React from 'react'; import * as React from 'react';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { FormInfo, FormName, PaymentTerminalFormValues, WalletFormInfo } from 'checkout/state'; import {
FormInfo,
FormName,
PaymentTerminalFormValues,
ResultFormInfo,
ResultType,
WalletFormInfo
} from 'checkout/state';
import { getMetadata, MetadataLogo, PaymentMethodItemContainer } from 'checkout/components/ui'; import { getMetadata, MetadataLogo, PaymentMethodItemContainer } from 'checkout/components/ui';
import { PaymentMethodName, ServiceProvider } from 'checkout/backend'; import { PaymentMethodName, ServiceProvider } from 'checkout/backend';
import { PaymentRequestedPayload, goToFormInfo, pay, prepareToPay } from 'checkout/actions'; import { PaymentRequestedPayload, goToFormInfo, pay, prepareToPay } from 'checkout/actions';
@ -19,7 +26,7 @@ export interface WalletProviderPaymentMethodItemProps {
export const WalletProviderPaymentMethodItem = ({ serviceProvider }: WalletProviderPaymentMethodItemProps) => { export const WalletProviderPaymentMethodItem = ({ serviceProvider }: WalletProviderPaymentMethodItemProps) => {
const { logo, form } = getMetadata(serviceProvider); const { logo, form } = getMetadata(serviceProvider);
const { paymentPayload, setFormData } = useCreatePayment(); const { createPaymentState, setFormData } = useCreatePayment();
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const onClick = () => { const onClick = () => {
@ -37,10 +44,13 @@ export const WalletProviderPaymentMethodItem = ({ serviceProvider }: WalletProvi
}; };
useEffect(() => { useEffect(() => {
if (!isNil(paymentPayload)) { if (createPaymentState.status === 'SUCCESS') {
dispatch(pay(paymentPayload)); dispatch(pay(createPaymentState.data));
} }
}, [paymentPayload]); if (createPaymentState.status === 'FAILURE') {
dispatch(goToFormInfo(new ResultFormInfo(ResultType.hookError, createPaymentState.error)));
}
}, [createPaymentState]);
return ( return (
<PaymentMethodItemContainer onClick={onClick}> <PaymentMethodItemContainer onClick={onClick}>

View File

@ -1,4 +1,4 @@
import { useContext, useState, useCallback } from 'react'; import { useContext, useCallback, useReducer } from 'react';
import isNil from 'checkout/utils/is-nil'; import isNil from 'checkout/utils/is-nil';
import { PaymentRequestedPayload } from 'checkout/actions'; import { PaymentRequestedPayload } from 'checkout/actions';
@ -8,6 +8,32 @@ import { FormData } from './create-payment';
import { InitialContext } from '../components/app/initial-context'; import { InitialContext } from '../components/app/initial-context';
import { PayableInvoiceContext } from '../components/app/modal-container/payable-invoice-context'; import { PayableInvoiceContext } from '../components/app/modal-container/payable-invoice-context';
type State =
| { status: 'PRISTINE' }
| { status: 'SUCCESS'; data: PaymentRequestedPayload }
| { status: 'FAILURE'; error: unknown };
type Action =
| { type: 'CREATE_PAYMENT_SUCCESS'; payload: PaymentRequestedPayload }
| { type: 'CREATE_PAYMENT_FAILURE'; error: unknown };
const dataReducer = (state: State, action: Action): State => {
switch (action.type) {
case 'CREATE_PAYMENT_SUCCESS':
return {
...state,
status: 'SUCCESS',
data: action.payload
};
case 'CREATE_PAYMENT_FAILURE':
return {
...state,
status: 'FAILURE',
error: action.error
};
}
};
export const useCreatePayment = () => { export const useCreatePayment = () => {
const { const {
initConfig, initConfig,
@ -18,51 +44,58 @@ export const useCreatePayment = () => {
} = useContext(InitialContext); } = useContext(InitialContext);
const { payableInvoiceData, setPayableInvoiceData } = useContext(PayableInvoiceContext); const { payableInvoiceData, setPayableInvoiceData } = useContext(PayableInvoiceContext);
const [paymentPayload, setPaymentPayload] = useState<PaymentRequestedPayload>(null); const [createPaymentState, dispatch] = useReducer(dataReducer, {
status: 'PRISTINE'
});
const setFormData = useCallback( const setFormData = useCallback(
(formData: FormData) => { (formData: FormData) => {
const fetchData = async () => { const fetchData = async () => {
let data = payableInvoiceData; try {
if (isNil(data)) { let data = payableInvoiceData;
data = await createInvoiceWithTemplate({ if (isNil(data)) {
data = await createInvoiceWithTemplate({
capiEndpoint: appConfig.capiEndpoint,
invoiceTemplateAccessToken: initConfig.invoiceTemplateAccessToken,
invoiceTemplate,
amountInfo,
formAmount: formData.values?.amount
});
setPayableInvoiceData(data);
}
await createPayment({
capiEndpoint: appConfig.capiEndpoint, capiEndpoint: appConfig.capiEndpoint,
invoiceTemplateAccessToken: initConfig.invoiceTemplateAccessToken, urlShortenerEndpoint: appConfig.urlShortenerEndpoint,
invoiceTemplate, origin,
amountInfo, initConfig: {
formAmount: formData.values?.amount redirectUrl: initConfig.redirectUrl,
email: initConfig.email,
phoneNumber: initConfig.phoneNumber,
paymentFlowHold: initConfig.paymentFlowHold,
holdExpiration: initConfig.holdExpiration,
recurring: initConfig.recurring,
metadata: initConfig.metadata,
isExternalIDIncluded: initConfig.isExternalIDIncluded
},
formData,
payableInvoice: data
}); });
setPayableInvoiceData(data); const payload = {
capiEndpoint: appConfig.capiEndpoint,
invoiceID: data.invoice.id,
invoiceAccessToken: data.invoiceAccessToken,
serviceProviders
};
dispatch({ type: 'CREATE_PAYMENT_SUCCESS', payload });
} catch (error) {
dispatch({ type: 'CREATE_PAYMENT_FAILURE', error });
console.error('Create payment failure', error);
} }
await createPayment({
capiEndpoint: appConfig.capiEndpoint,
urlShortenerEndpoint: appConfig.urlShortenerEndpoint,
origin,
initConfig: {
redirectUrl: initConfig.redirectUrl,
email: initConfig.email,
phoneNumber: initConfig.phoneNumber,
paymentFlowHold: initConfig.paymentFlowHold,
holdExpiration: initConfig.holdExpiration,
recurring: initConfig.recurring,
metadata: initConfig.metadata,
isExternalIDIncluded: initConfig.isExternalIDIncluded
},
formData,
payableInvoice: data
});
setPaymentPayload({
capiEndpoint: appConfig.capiEndpoint,
invoiceID: data.invoice.id,
invoiceAccessToken: data.invoiceAccessToken,
serviceProviders
});
}; };
fetchData(); fetchData();
}, },
[payableInvoiceData] [payableInvoiceData]
); );
return { paymentPayload, setFormData }; return { createPaymentState, setFormData };
}; };

View File

@ -2,16 +2,19 @@ import { FormInfo, FormName } from '../form-info';
export enum ResultType { export enum ResultType {
error = 'error', error = 'error',
processed = 'processed' processed = 'processed',
hookError = 'hookError'
} }
export class ResultFormInfo extends FormInfo { export class ResultFormInfo extends FormInfo {
resultType: ResultType; resultType: ResultType;
hookError?: unknown;
constructor(resultType: ResultType) { constructor(resultType: ResultType, hookError?: unknown) {
super(); super();
this.name = FormName.resultForm; this.name = FormName.resultForm;
this.resultType = resultType; this.resultType = resultType;
this.active = true; this.active = true;
this.hookError = hookError;
} }
} }