From 15a30f0c80c99e4bbb2c9b31b41d36228ce6bd4a Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Tue, 11 Oct 2022 11:47:26 +0400 Subject: [PATCH 1/9] Add new command VerifyIdentityForBankAccount --- src/libs/actions/BankAccounts.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 746106e0263e..1de275a32d2f 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -293,16 +293,30 @@ function connectBankAccountManually(bankAccountID, accountNumber, routingNumber, }, getVBBADataForOnyx()); } +/** + * Verify the user's identity via Onfido + * + * @param {Number} bankAccountID + * @param {Object} onfidoData + */ + function verifyIdentityForBankAccount(bankAccountID, onfidoData) { + API.write('VerifyIdentityForBankAccount', { + bankAccountID, + onfidoData: JSON.stringify(onfidoData), + }, getVBBADataForOnyx()); +} + export { addPersonalBankAccount, connectBankAccountManually, - deletePaymentBankAccount, clearPersonalBankAccount, clearPlaid, clearOnfidoToken, - updatePersonalInformationForBankAccount, - validateBankAccount, - updateCompanyInformationForBankAccount, connectBankAccountWithPlaid, + deletePaymentBankAccount, + updateCompanyInformationForBankAccount, + updatePersonalInformationForBankAccount, updatePlaidData, + validateBankAccount, + verifyIdentityForBankAccount, }; From 95e41dc92e54d9fde595d54bd94379e1388b0ea7 Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Tue, 11 Oct 2022 11:48:26 +0400 Subject: [PATCH 2/9] Add new component for Onfido flow during Requestor step --- src/libs/actions/BankAccounts.js | 2 +- .../RequestorOnfidoStep.js | 82 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 src/pages/ReimbursementAccount/RequestorOnfidoStep.js diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 1de275a32d2f..a1d8f47a4731 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -299,7 +299,7 @@ function connectBankAccountManually(bankAccountID, accountNumber, routingNumber, * @param {Number} bankAccountID * @param {Object} onfidoData */ - function verifyIdentityForBankAccount(bankAccountID, onfidoData) { +function verifyIdentityForBankAccount(bankAccountID, onfidoData) { API.write('VerifyIdentityForBankAccount', { bankAccountID, onfidoData: JSON.stringify(onfidoData), diff --git a/src/pages/ReimbursementAccount/RequestorOnfidoStep.js b/src/pages/ReimbursementAccount/RequestorOnfidoStep.js new file mode 100644 index 000000000000..82b17d641d35 --- /dev/null +++ b/src/pages/ReimbursementAccount/RequestorOnfidoStep.js @@ -0,0 +1,82 @@ +import React from 'react'; +import {ScrollView} from 'react-native'; +import {withOnyx} from 'react-native-onyx'; +import PropTypes from 'prop-types'; +import styles from '../../styles/styles'; +import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize'; +import * as BankAccounts from '../../libs/actions/BankAccounts'; +import Onfido from '../../components/Onfido'; +import compose from '../../libs/compose'; +import ONYXKEYS from '../../ONYXKEYS'; +import * as ReimbursementAccountUtils from '../../libs/ReimbursementAccountUtils'; +import Growl from '../../libs/Growl'; +import reimbursementAccountPropTypes from './reimbursementAccountPropTypes'; +import CONST from '../../CONST'; + +const propTypes = { + /** Bank account currently in setup */ + /* eslint-disable-next-line react/no-unused-prop-types */ + reimbursementAccount: reimbursementAccountPropTypes.isRequired, + onfidoToken: PropTypes.string, + onComplete: PropTypes.func.isRequired, + ...withLocalizePropTypes, +}; + +const defaultProps = { + onfidoToken: '', +}; + +class RequestorOnfidoStep extends React.Component { + constructor(props) { + super(props); + this.submit = this.submit.bind(this); + } + + submit(onfidoData) { + BankAccounts.verifyIdentityForBankAccount( + ReimbursementAccountUtils.getDefaultStateForField(this.props, 'bankAccountID', 0), + onfidoData, + ); + this.props.onComplete(); + } + + render() { + return ( + + { + // We're taking the user back to the company step. They will need to come back to the requestor step to make the Onfido flow appear again. + BankAccounts.goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COMPANY); + }} + onError={() => { + // In case of any unexpected error we log it to the server, show a growl, and return the user back to the company step so they can try again. + Growl.error(this.props.translate('onfidoStep.genericError'), 10000); + BankAccounts.goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COMPANY); + }} + onSuccess={(onfidoData) => { + this.submit(onfidoData); + }} + /> + + ); + } +} + +RequestorOnfidoStep.propTypes = propTypes; +RequestorOnfidoStep.defaultProps = defaultProps; + +export default compose( + withLocalize, + withOnyx({ + reimbursementAccount: { + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT, + }, + onfidoToken: { + key: ONYXKEYS.ONFIDO_TOKEN, + }, + reimbursementAccountDraft: { + key: ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, + }, + }), +)(RequestorOnfidoStep); From e4e7310d671e6129222f7d61a54ccc9f4d60bf7e Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Tue, 11 Oct 2022 11:54:21 +0400 Subject: [PATCH 3/9] Use RequestorOnfidoStep component --- .../ReimbursementAccount/RequestorStep.js | 51 +++++-------------- 1 file changed, 13 insertions(+), 38 deletions(-) diff --git a/src/pages/ReimbursementAccount/RequestorStep.js b/src/pages/ReimbursementAccount/RequestorStep.js index 6be190673464..bba0dba6b06d 100644 --- a/src/pages/ReimbursementAccount/RequestorStep.js +++ b/src/pages/ReimbursementAccount/RequestorStep.js @@ -1,6 +1,6 @@ import React from 'react'; import lodashGet from 'lodash/get'; -import {ScrollView, View} from 'react-native'; +import {View} from 'react-native'; import {withOnyx} from 'react-native-onyx'; import _ from 'underscore'; import moment from 'moment'; @@ -16,14 +16,13 @@ import Text from '../../components/Text'; import * as BankAccounts from '../../libs/actions/BankAccounts'; import IdentityForm from './IdentityForm'; import * as ValidationUtils from '../../libs/ValidationUtils'; -import Onfido from '../../components/Onfido'; import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; import * as ReimbursementAccountUtils from '../../libs/ReimbursementAccountUtils'; -import Growl from '../../libs/Growl'; import reimbursementAccountPropTypes from './reimbursementAccountPropTypes'; import ReimbursementAccountForm from './ReimbursementAccountForm'; import * as Link from '../../libs/actions/Link'; +import RequestorOnfidoStep from './RequestorOnfidoStep'; const propTypes = { /** Bank account currently in setup */ @@ -42,6 +41,7 @@ class RequestorStep extends React.Component { this.submit = this.submit.bind(this); this.clearErrorsAndSetValues = this.clearErrorsAndSetValues.bind(this); + this.setOnfidoAsComplete = this.setOnfidoAsComplete.bind(this); this.state = { firstName: ReimbursementAccountUtils.getDefaultStateForField(props, 'firstName'), @@ -53,7 +53,6 @@ class RequestorStep extends React.Component { dob: ReimbursementAccountUtils.getDefaultStateForField(props, 'dob'), ssnLast4: ReimbursementAccountUtils.getDefaultStateForField(props, 'ssnLast4'), isControllingOfficer: ReimbursementAccountUtils.getDefaultStateForField(props, 'isControllingOfficer', false), - onfidoData: lodashGet(props, ['reimbursementAccount', 'achData', 'onfidoData'], ''), isOnfidoSetupComplete: lodashGet(props, ['achData', 'isOnfidoSetupComplete'], false), }; @@ -74,6 +73,13 @@ class RequestorStep extends React.Component { this.getErrors = () => ReimbursementAccountUtils.getErrors(this.props); } + /** + * Update state to indicate that the user has completed the Onfido verification process + */ + setOnfidoAsComplete() { + this.setState({isOnfidoSetupComplete: true}); + } + /** * Clear the errors associated to keys in values if found and store the new values in the state. * @@ -147,20 +153,6 @@ class RequestorStep extends React.Component { BankAccounts.updatePersonalInformationForBankAccount(payload); } - submitOnfidoVerification() { - if (!this.validate()) { - return; - } - - const payload = { - bankAccountID: ReimbursementAccountUtils.getDefaultStateForField(this.props, 'bankAccountID', 0), - ...this.state, - dob: moment(this.state.dob).format(CONST.DATE.MOMENT_FORMAT_STRING), - }; - - BankAccounts.setupWithdrawalAccount(payload); - } - render() { const achData = this.props.reimbursementAccount.achData; const shouldShowOnfido = achData.useOnfido && this.props.onfidoToken && !this.state.isOnfidoSetupComplete; @@ -183,26 +175,9 @@ class RequestorStep extends React.Component { onCloseButtonPress={Navigation.dismissModal} /> {shouldShowOnfido ? ( - - { - // We're taking the user back to the company step. They will need to come back to the requestor step to make the Onfido flow appear again. - BankAccounts.goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COMPANY); - }} - onError={() => { - // In case of any unexpected error we log it to the server, show a growl, and return the user back to the company step so they can try again. - Growl.error(this.props.translate('onfidoStep.genericError'), 10000); - BankAccounts.goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.COMPANY); - }} - onSuccess={(onfidoData) => { - this.setState({ - onfidoData, - isOnfidoSetupComplete: true, - }, this.submitOnfidoVerification); - }} - /> - + ) : ( Date: Tue, 18 Oct 2022 10:51:38 +0400 Subject: [PATCH 4/9] Add reimbursement account draft to prop types --- src/pages/ReimbursementAccount/RequestorOnfidoStep.js | 3 +++ src/pages/ReimbursementAccount/RequestorStep.js | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/pages/ReimbursementAccount/RequestorOnfidoStep.js b/src/pages/ReimbursementAccount/RequestorOnfidoStep.js index 82b17d641d35..af736c34c657 100644 --- a/src/pages/ReimbursementAccount/RequestorOnfidoStep.js +++ b/src/pages/ReimbursementAccount/RequestorOnfidoStep.js @@ -11,12 +11,15 @@ import ONYXKEYS from '../../ONYXKEYS'; import * as ReimbursementAccountUtils from '../../libs/ReimbursementAccountUtils'; import Growl from '../../libs/Growl'; import reimbursementAccountPropTypes from './reimbursementAccountPropTypes'; +import reimbursementAccountDraftPropTypes from './reimbursementAccountDraftPropTypes'; import CONST from '../../CONST'; const propTypes = { /** Bank account currently in setup */ /* eslint-disable-next-line react/no-unused-prop-types */ reimbursementAccount: reimbursementAccountPropTypes.isRequired, + /* eslint-disable-next-line react/no-unused-prop-types */ + reimbursementAccountDraft: reimbursementAccountDraftPropTypes.isRequired, onfidoToken: PropTypes.string, onComplete: PropTypes.func.isRequired, ...withLocalizePropTypes, diff --git a/src/pages/ReimbursementAccount/RequestorStep.js b/src/pages/ReimbursementAccount/RequestorStep.js index bba0dba6b06d..bb3e7dc3b069 100644 --- a/src/pages/ReimbursementAccount/RequestorStep.js +++ b/src/pages/ReimbursementAccount/RequestorStep.js @@ -20,6 +20,7 @@ import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; import * as ReimbursementAccountUtils from '../../libs/ReimbursementAccountUtils'; import reimbursementAccountPropTypes from './reimbursementAccountPropTypes'; +import reimbursementAccountDraftPropTypes from './reimbursementAccountDraftPropTypes'; import ReimbursementAccountForm from './ReimbursementAccountForm'; import * as Link from '../../libs/actions/Link'; import RequestorOnfidoStep from './RequestorOnfidoStep'; @@ -27,6 +28,8 @@ import RequestorOnfidoStep from './RequestorOnfidoStep'; const propTypes = { /** Bank account currently in setup */ reimbursementAccount: reimbursementAccountPropTypes.isRequired, + /* eslint-disable-next-line react/no-unused-prop-types */ + reimbursementAccountDraft: reimbursementAccountDraftPropTypes.isRequired, onfidoToken: PropTypes.string, ...withLocalizePropTypes, }; From 123c9cf9eb50b40e327bdf6fbc2962eadeaf0cf4 Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Tue, 18 Oct 2022 10:55:45 +0400 Subject: [PATCH 5/9] Update prop type --- .../ReimbursementAccount/ReimbursementAccountDraftPropTypes.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/ReimbursementAccount/ReimbursementAccountDraftPropTypes.js b/src/pages/ReimbursementAccount/ReimbursementAccountDraftPropTypes.js index 2261c0b472d6..98cbd1fdc0da 100644 --- a/src/pages/ReimbursementAccount/ReimbursementAccountDraftPropTypes.js +++ b/src/pages/ReimbursementAccount/ReimbursementAccountDraftPropTypes.js @@ -33,7 +33,7 @@ export default PropTypes.shape({ requestorAddressZipCode: PropTypes.string, dob: PropTypes.string, ssnLast4: PropTypes.string, - isControllingOfficer: PropTypes.string, + isControllingOfficer: PropTypes.bool, isOnfidoSetupComplete: PropTypes.bool, /** Props needed for ACHContractStep */ From a98eb9ac4434e0e73cb7f0a19f0fdd2e75cb6f78 Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Tue, 18 Oct 2022 11:09:26 +0400 Subject: [PATCH 6/9] Fix propTypes for BankAccountStep --- src/pages/ReimbursementAccount/BankAccountStep.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/pages/ReimbursementAccount/BankAccountStep.js b/src/pages/ReimbursementAccount/BankAccountStep.js index 59c94c7688a6..048f38fe3fd0 100644 --- a/src/pages/ReimbursementAccount/BankAccountStep.js +++ b/src/pages/ReimbursementAccount/BankAccountStep.js @@ -26,6 +26,7 @@ import CONFIG from '../../CONFIG'; import ROUTES from '../../ROUTES'; import Button from '../../components/Button'; import plaidDataPropTypes from './plaidDataPropTypes'; +import reimbursementAccountPropTypes from './reimbursementAccountPropTypes'; const propTypes = { /** Contains plaid data */ @@ -37,6 +38,10 @@ const propTypes = { /** During the OAuth flow we need to use the plaidLink token that we initially connected with */ plaidLinkOAuthToken: PropTypes.string, + /** The bank account currently in setup */ + /* eslint-disable-next-line react/no-unused-prop-types */ + reimbursementAccount: reimbursementAccountPropTypes, + /** Object with various information about the user */ user: PropTypes.shape({ /** Is the user account validated? */ @@ -52,6 +57,7 @@ const defaultProps = { plaidData: { isPlaidDisabled: false, }, + reimbursementAccount: {}, user: {}, }; From e03a8d7c9d88407016be01164e321cbf96a624e9 Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Tue, 18 Oct 2022 11:11:25 +0400 Subject: [PATCH 7/9] Fix propTypes for CompanyStep --- src/pages/ReimbursementAccount/CompanyStep.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js index ec3aef995f6b..29fba0a47a8e 100644 --- a/src/pages/ReimbursementAccount/CompanyStep.js +++ b/src/pages/ReimbursementAccount/CompanyStep.js @@ -26,8 +26,18 @@ import AddressForm from './AddressForm'; import ReimbursementAccountForm from './ReimbursementAccountForm'; import * as ReimbursementAccount from '../../libs/actions/ReimbursementAccount'; import * as ReimbursementAccountUtils from '../../libs/ReimbursementAccountUtils'; +import reimbursementAccountPropTypes from './reimbursementAccountPropTypes'; +import reimbursementAccountDraftPropTypes from './reimbursementAccountDraftPropTypes'; const propTypes = { + /** The bank account currently in setup */ + /* eslint-disable-next-line react/no-unused-prop-types */ + reimbursementAccount: reimbursementAccountPropTypes.isRequired, + + /** The draft values of the bank account being setup */ + /* eslint-disable-next-line react/no-unused-prop-types */ + reimbursementAccountDraft: reimbursementAccountDraftPropTypes.isRequired, + ...withLocalizePropTypes, }; From 75ab5b927686afee847095109a7c935a7858c355 Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Tue, 18 Oct 2022 11:13:04 +0400 Subject: [PATCH 8/9] Fix propTypes for RequestorStep --- .../ReimbursementAccount/RequestorOnfidoStep.js | 13 +++++++++---- src/pages/ReimbursementAccount/RequestorStep.js | 7 ++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/pages/ReimbursementAccount/RequestorOnfidoStep.js b/src/pages/ReimbursementAccount/RequestorOnfidoStep.js index af736c34c657..d10729d8121a 100644 --- a/src/pages/ReimbursementAccount/RequestorOnfidoStep.js +++ b/src/pages/ReimbursementAccount/RequestorOnfidoStep.js @@ -18,16 +18,21 @@ const propTypes = { /** Bank account currently in setup */ /* eslint-disable-next-line react/no-unused-prop-types */ reimbursementAccount: reimbursementAccountPropTypes.isRequired, + + /** The draft values of the bank account being setup */ /* eslint-disable-next-line react/no-unused-prop-types */ reimbursementAccountDraft: reimbursementAccountDraftPropTypes.isRequired, - onfidoToken: PropTypes.string, + + /** The token required to initialize the Onfido SDK */ + onfidoToken: PropTypes.string.isRequired, + + /** A callback to call once the user completes the Onfido flow */ onComplete: PropTypes.func.isRequired, + ...withLocalizePropTypes, }; -const defaultProps = { - onfidoToken: '', -}; +const defaultProps = {}; class RequestorOnfidoStep extends React.Component { constructor(props) { diff --git a/src/pages/ReimbursementAccount/RequestorStep.js b/src/pages/ReimbursementAccount/RequestorStep.js index bb3e7dc3b069..414cf136e6ce 100644 --- a/src/pages/ReimbursementAccount/RequestorStep.js +++ b/src/pages/ReimbursementAccount/RequestorStep.js @@ -26,11 +26,16 @@ import * as Link from '../../libs/actions/Link'; import RequestorOnfidoStep from './RequestorOnfidoStep'; const propTypes = { - /** Bank account currently in setup */ + /** The bank account currently in setup */ reimbursementAccount: reimbursementAccountPropTypes.isRequired, + + /** The draft values of the bank account being setup */ /* eslint-disable-next-line react/no-unused-prop-types */ reimbursementAccountDraft: reimbursementAccountDraftPropTypes.isRequired, + + /** The token required to initialize the Onfido SDK */ onfidoToken: PropTypes.string, + ...withLocalizePropTypes, }; From aa460a9c0630dd5b942c0a0de621450ad698494d Mon Sep 17 00:00:00 2001 From: Maria D'Costa Date: Tue, 18 Oct 2022 17:23:00 +0400 Subject: [PATCH 9/9] Fix linter error Missing file extension for "./reimbursementAccountDraftPropTypes" --- src/pages/ReimbursementAccount/CompanyStep.js | 2 +- src/pages/ReimbursementAccount/RequestorOnfidoStep.js | 2 +- src/pages/ReimbursementAccount/RequestorStep.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/ReimbursementAccount/CompanyStep.js b/src/pages/ReimbursementAccount/CompanyStep.js index 29fba0a47a8e..0f122c1fbda4 100644 --- a/src/pages/ReimbursementAccount/CompanyStep.js +++ b/src/pages/ReimbursementAccount/CompanyStep.js @@ -27,7 +27,7 @@ import ReimbursementAccountForm from './ReimbursementAccountForm'; import * as ReimbursementAccount from '../../libs/actions/ReimbursementAccount'; import * as ReimbursementAccountUtils from '../../libs/ReimbursementAccountUtils'; import reimbursementAccountPropTypes from './reimbursementAccountPropTypes'; -import reimbursementAccountDraftPropTypes from './reimbursementAccountDraftPropTypes'; +import reimbursementAccountDraftPropTypes from './ReimbursementAccountDraftPropTypes'; const propTypes = { /** The bank account currently in setup */ diff --git a/src/pages/ReimbursementAccount/RequestorOnfidoStep.js b/src/pages/ReimbursementAccount/RequestorOnfidoStep.js index d10729d8121a..0101bd216c5f 100644 --- a/src/pages/ReimbursementAccount/RequestorOnfidoStep.js +++ b/src/pages/ReimbursementAccount/RequestorOnfidoStep.js @@ -11,7 +11,7 @@ import ONYXKEYS from '../../ONYXKEYS'; import * as ReimbursementAccountUtils from '../../libs/ReimbursementAccountUtils'; import Growl from '../../libs/Growl'; import reimbursementAccountPropTypes from './reimbursementAccountPropTypes'; -import reimbursementAccountDraftPropTypes from './reimbursementAccountDraftPropTypes'; +import reimbursementAccountDraftPropTypes from './ReimbursementAccountDraftPropTypes'; import CONST from '../../CONST'; const propTypes = { diff --git a/src/pages/ReimbursementAccount/RequestorStep.js b/src/pages/ReimbursementAccount/RequestorStep.js index 414cf136e6ce..70e00a46b96e 100644 --- a/src/pages/ReimbursementAccount/RequestorStep.js +++ b/src/pages/ReimbursementAccount/RequestorStep.js @@ -20,7 +20,7 @@ import compose from '../../libs/compose'; import ONYXKEYS from '../../ONYXKEYS'; import * as ReimbursementAccountUtils from '../../libs/ReimbursementAccountUtils'; import reimbursementAccountPropTypes from './reimbursementAccountPropTypes'; -import reimbursementAccountDraftPropTypes from './reimbursementAccountDraftPropTypes'; +import reimbursementAccountDraftPropTypes from './ReimbursementAccountDraftPropTypes'; import ReimbursementAccountForm from './ReimbursementAccountForm'; import * as Link from '../../libs/actions/Link'; import RequestorOnfidoStep from './RequestorOnfidoStep';