diff --git a/src/CONST.js b/src/CONST.js
index 5c1fd52f8798..d85dd5a36e15 100755
--- a/src/CONST.js
+++ b/src/CONST.js
@@ -430,6 +430,7 @@ const CONST = {
FULL_SSN_NOT_FOUND: 'Full SSN not found',
MISSING_FIELD: 'Missing required additional details fields',
WRONG_ANSWERS: 'Wrong answers',
+ ONFIDO_FIXABLE_ERROR: 'Onfido returned a fixable error',
// KBA stands for Knowledge Based Answers (requiring us to show Idology questions)
KBA_NEEDED: 'KBA needed',
@@ -442,8 +443,8 @@ const CONST = {
},
STEP: {
// In the order they appear in the Wallet flow
- ONFIDO: 'OnfidoStep',
ADDITIONAL_DETAILS: 'AdditionalDetailsStep',
+ ONFIDO: 'OnfidoStep',
TERMS: 'TermsStep',
ACTIVATE: 'ActivateStep',
},
diff --git a/src/languages/en.js b/src/languages/en.js
index a17924c1f7dc..f70ec35135cd 100755
--- a/src/languages/en.js
+++ b/src/languages/en.js
@@ -567,6 +567,12 @@ export default {
genericError: 'There was an error while processing this step. Please try again.',
cameraPermissionsNotGranted: 'Camera permissions not granted',
cameraRequestMessage: 'You have not granted us camera access. We need access to complete verification.',
+ originalDocumentNeeded: 'Please upload an original image of your ID rather than a screenshot or scanned image.',
+ documentNeedsBetterQuality: 'Your ID appears to be damaged or has missing security features. Please upload an original image of an undamaged ID that is entirely visible.',
+ imageNeedsBetterQuality: 'There\'s an issue with the image quality of your ID. Please upload a new image where your entire ID can be seen clearly.',
+ selfieIssue: 'There\'s an issue with your selfie/video. Please upload a new selfie/video in real time.',
+ selfieNotMatching: 'Your selfie/video doesn\'t match your ID. Please upload a new selfie/video where your face can be clearly seen.',
+ selfieNotLive: 'Your selfie/video doesn\'t appear to be a live photo/video. Please upload a live selfie/video.',
},
additionalDetailsStep: {
headerTitle: 'Additional details',
diff --git a/src/languages/es.js b/src/languages/es.js
index a247568bb3e5..a401e6811437 100644
--- a/src/languages/es.js
+++ b/src/languages/es.js
@@ -567,6 +567,12 @@ export default {
genericError: 'Hubo un error al procesar este paso. Inténtalo de nuevo.',
cameraPermissionsNotGranted: 'No has habilitado los permisos para acceder a la cámara',
cameraRequestMessage: 'No has habilitado los permisos para acceder a la cámara. Necesitamos acceso para completar la verificaciôn.',
+ originalDocumentNeeded: 'Por favor, sube una imagen original de tu identificación en lugar de una captura de pantalla o imagen escaneada.',
+ documentNeedsBetterQuality: 'Parece que tu identificación esta dañado o le faltan características de seguridad. Por favor, sube una imagen de tu documento sin daños y que se vea completamente.',
+ imageNeedsBetterQuality: 'Hay un problema con la calidad de la imagen de tu identificación. Por favor, sube una nueva imagen donde el identificación se vea con claridad.',
+ selfieIssue: 'Hay un problema con tu selfie/video. Por favor, sube un nuevo selfie/video grabado en el momento',
+ selfieNotMatching: 'Tu selfie/video no concuerda con tu identificación. Por favor, sube un nuevo selfie/video donde se vea tu cara con claridad.',
+ selfieNotLive: 'Tu selfie/video no parece ser un selfie/video en vivo. Por favor, sube un selfie/video a tiempo real.',
},
additionalDetailsStep: {
headerTitle: 'Detalles adicionales',
diff --git a/src/libs/API.js b/src/libs/API.js
index 1fbfe935e5bf..0b32d2c245b7 100644
--- a/src/libs/API.js
+++ b/src/libs/API.js
@@ -898,14 +898,20 @@ function CreateIOUSplit(parameters) {
}
/**
+ * @param {String} firstName
+ * @param {String} lastName
+ * @param {String} dob
* @returns {Promise}
*/
-function Wallet_GetOnfidoSDKToken() {
+function Wallet_GetOnfidoSDKToken(firstName, lastName, dob) {
return Network.post('Wallet_GetOnfidoSDKToken', {
// We need to pass this so we can request a token with the correct referrer
// This value comes from a cross-platform module which returns true for native
// platforms and false for non-native platforms.
isViaExpensifyCashNative,
+ firstName,
+ lastName,
+ dob,
}, CONST.NETWORK.METHOD.POST, true);
}
diff --git a/src/libs/actions/PersonalDetails.js b/src/libs/actions/PersonalDetails.js
index 0fe6cd893dcf..fdad13b97569 100644
--- a/src/libs/actions/PersonalDetails.js
+++ b/src/libs/actions/PersonalDetails.js
@@ -147,6 +147,43 @@ function fetchPersonalDetails() {
});
}
+/**
+ * Gets the first and last name from the user's personal details.
+ * If the login is the same as the displayName, then they don't exist,
+ * so we return empty strings instead.
+ * @param {Object} personalDetail
+ * @param {String} personalDetail.login
+ * @param {String} personalDetail.displayName
+ * @param {String} personalDetail.firstName
+ * @param {String} personalDetail.lastName
+ *
+ * @returns {Object}
+ */
+function extractFirstAndLastNameFromAvailableDetails({
+ login,
+ displayName,
+ firstName,
+ lastName,
+}) {
+ if (firstName || lastName) {
+ return {firstName: firstName || '', lastName: lastName || ''};
+ }
+ if (Str.removeSMSDomain(login) === displayName) {
+ return {firstName: '', lastName: ''};
+ }
+
+ const firstSpaceIndex = displayName.indexOf(' ');
+ const lastSpaceIndex = displayName.lastIndexOf(' ');
+ if (firstSpaceIndex === -1) {
+ return {firstName: displayName, lastName: ''};
+ }
+
+ return {
+ firstName: displayName.substring(0, firstSpaceIndex).trim(),
+ lastName: displayName.substring(lastSpaceIndex).trim(),
+ };
+}
+
/**
* Get personal details from report participants.
*
@@ -350,4 +387,5 @@ export {
fetchLocalCurrency,
getCurrencyList,
getMaxCharacterError,
+ extractFirstAndLastNameFromAvailableDetails,
};
diff --git a/src/libs/actions/Wallet.js b/src/libs/actions/Wallet.js
index 05fb2e8dc7b8..9ff5c67fce1b 100644
--- a/src/libs/actions/Wallet.js
+++ b/src/libs/actions/Wallet.js
@@ -13,11 +13,14 @@ import * as Localize from '../Localize';
* - The sdkToken is used to initialize the Onfido SDK client
* - The applicantID is combined with the data returned from the Onfido SDK as we need both to create an
* identity check. Note: This happens in Web-Secure when we call Activate_Wallet during the OnfidoStep.
+ * @param {String} firstName
+ * @param {String} lastName
+ * @param {String} dob
*/
-function fetchOnfidoToken() {
+function fetchOnfidoToken(firstName, lastName, dob) {
// Use Onyx.set() since we are resetting the Onfido flow completely.
Onyx.set(ONYXKEYS.WALLET_ONFIDO, {loading: true});
- API.Wallet_GetOnfidoSDKToken()
+ API.Wallet_GetOnfidoSDKToken(firstName, lastName, dob)
.then((response) => {
const apiResult = lodashGet(response, ['requestorIdentityOnfido', 'apiResult'], {});
Onyx.merge(ONYXKEYS.WALLET_ONFIDO, {
@@ -71,8 +74,8 @@ function setAdditionalDetailsShouldAskForFullSSN(shouldAskForFullSSN) {
/**
* @param {Boolean} shouldShowFailedKYC
*/
-function setAdditionalDetailsShouldShowFailedKYC(shouldShowFailedKYC) {
- Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS, {shouldShowFailedKYC});
+function setWalletShouldShowFailedKYC(shouldShowFailedKYC) {
+ Onyx.merge(ONYXKEYS.USER_WALLET, {shouldShowFailedKYC});
}
/**
@@ -175,6 +178,7 @@ function activateWallet(currentStep, parameters) {
throw new Error('Invalid currentStep passed to activateWallet()');
}
+ setWalletShouldShowFailedKYC(false);
if (currentStep === CONST.WALLET.STEP.ONFIDO) {
onfidoData = parameters.onfidoData;
Onyx.merge(ONYXKEYS.WALLET_ONFIDO, {error: '', loading: true});
@@ -183,7 +187,6 @@ function activateWallet(currentStep, parameters) {
setAdditionalDetailsLoading(true);
setAdditionalDetailsErrors(null);
setAdditionalDetailsErrorMessage('');
- setAdditionalDetailsShouldShowFailedKYC(false);
personalDetails = JSON.stringify(parameters.personalDetails);
}
if (parameters.idologyAnswers) {
@@ -212,7 +215,12 @@ function activateWallet(currentStep, parameters) {
if (response.jsonCode !== 200) {
if (currentStep === CONST.WALLET.STEP.ONFIDO) {
- Onyx.merge(ONYXKEYS.WALLET_ONFIDO, {error: response.message, loading: false});
+ Onyx.merge(ONYXKEYS.WALLET_ONFIDO, {loading: false});
+ if (response.title === CONST.WALLET.ERROR.ONFIDO_FIXABLE_ERROR) {
+ Onyx.merge(ONYXKEYS.WALLET_ONFIDO, {fixableErrors: lodashGet(response, 'data.fixableErrors', [])});
+ return;
+ }
+ setWalletShouldShowFailedKYC(true);
return;
}
@@ -257,7 +265,7 @@ function activateWallet(currentStep, parameters) {
'resultcode.pa.dob.does.not.match',
];
if (_.some(hardFailures, hardFailure => _.contains(idologyErrors, hardFailure))) {
- setAdditionalDetailsShouldShowFailedKYC(true);
+ setWalletShouldShowFailedKYC(true);
return;
}
@@ -270,7 +278,7 @@ function activateWallet(currentStep, parameters) {
if (lodashGet(response, 'data.requestorIdentityID.apiResult.results.key') === 'result.no.match'
|| response.title === CONST.WALLET.ERROR.WRONG_ANSWERS) {
- setAdditionalDetailsShouldShowFailedKYC(true);
+ setWalletShouldShowFailedKYC(true);
return;
}
if (Str.endsWith(response.type, 'AutoVerifyFailure')) {
@@ -318,7 +326,8 @@ function fetchUserWallet() {
return;
}
- Onyx.merge(ONYXKEYS.USER_WALLET, response.userWallet);
+ // When refreshing the wallet, we should not show the failed KYC page anymore, as we should allow them to retry.
+ Onyx.merge(ONYXKEYS.USER_WALLET, {...response.userWallet, shouldShowFailedKYC: false});
});
}
@@ -329,6 +338,13 @@ function updateAdditionalDetailsDraft(keyValuePair) {
Onyx.merge(ONYXKEYS.WALLET_ADDITIONAL_DETAILS_DRAFT, keyValuePair);
}
+/**
+ * @param {String} currentStep
+ */
+function updateCurrentStep(currentStep) {
+ Onyx.merge(ONYXKEYS.USER_WALLET, {currentStep});
+}
+
export {
fetchOnfidoToken,
activateWallet,
@@ -338,4 +354,5 @@ export {
setAdditionalDetailsErrorMessage,
setAdditionalDetailsQuestions,
buildIdologyError,
+ updateCurrentStep,
};
diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.js b/src/pages/EnablePayments/AdditionalDetailsStep.js
index 1fc82c82354e..58c96e46f58d 100644
--- a/src/pages/EnablePayments/AdditionalDetailsStep.js
+++ b/src/pages/EnablePayments/AdditionalDetailsStep.js
@@ -26,7 +26,9 @@ import * as ValidationUtils from '../../libs/ValidationUtils';
import AddressSearch from '../../components/AddressSearch';
import DatePicker from '../../components/DatePicker';
import FormHelper from '../../libs/FormHelper';
-import FailedKYC from './FailedKYC';
+import walletAdditionalDetailsDraftPropTypes from './walletAdditionalDetailsDraftPropTypes';
+import personalDetailsPropType from '../personalDetailsPropType';
+import * as PersonalDetails from '../../libs/actions/PersonalDetails';
const propTypes = {
...withLocalizePropTypes,
@@ -52,25 +54,15 @@ const propTypes = {
/** ExpectID ID number related to those questions */
idNumber: PropTypes.string,
- /** If we should show the FailedKYC view after the user submitted the form with a non fixable error */
- shouldShowFailedKYC: PropTypes.bool,
-
/** If we should ask for the full SSN (when LexisNexis failed retrieving the first 5 from the last 4) */
shouldAskForFullSSN: PropTypes.bool,
}),
/** Stores the personal details typed by the user */
- walletAdditionalDetailsDraft: PropTypes.shape({
- legalFirstName: PropTypes.string,
- legalLastName: PropTypes.string,
- addressStreet: PropTypes.string,
- addressCity: PropTypes.string,
- addressState: PropTypes.string,
- addressZip: PropTypes.string,
- phoneNumber: PropTypes.string,
- dob: PropTypes.string,
- ssn: PropTypes.string,
- }),
+ walletAdditionalDetailsDraft: walletAdditionalDetailsDraftPropTypes,
+
+ /** The personal details of the person who is logged in */
+ myPersonalDetails: personalDetailsPropType.isRequired,
};
const defaultProps = {
@@ -80,7 +72,6 @@ const defaultProps = {
additionalErrorMessage: '',
questions: [],
idNumber: '',
- shouldShowFailedKYC: false,
shouldAskForFullSSN: false,
},
walletAdditionalDetailsDraft: {
@@ -212,20 +203,6 @@ class AdditionalDetailsStep extends React.Component {
}
render() {
- if (this.props.walletAdditionalDetails.shouldShowFailedKYC) {
- return (
-
-
- Navigation.dismissModal()}
- />
-
-
-
- );
- }
-
if (!_.isEmpty(this.props.walletAdditionalDetails.questions)) {
return (
@@ -248,6 +225,7 @@ class AdditionalDetailsStep extends React.Component {
const isErrorVisible = _.size(this.getErrors()) > 0
|| lodashGet(this.props, 'walletAdditionalDetails.additionalErrorMessage', '').length > 0;
const shouldAskForFullSSN = this.props.walletAdditionalDetails.shouldAskForFullSSN;
+ const {firstName, lastName} = PersonalDetails.extractFirstAndLastNameFromAvailableDetails(this.props.myPersonalDetails);
return (
@@ -273,14 +251,14 @@ class AdditionalDetailsStep extends React.Component {
containerStyles={[styles.mt4]}
label={this.props.translate(this.fieldNameTranslationKeys.legalFirstName)}
onChangeText={val => this.clearErrorAndSetValue('legalFirstName', val)}
- value={this.props.walletAdditionalDetailsDraft.legalFirstName || ''}
+ value={this.props.walletAdditionalDetailsDraft.legalFirstName || firstName}
errorText={this.getErrorText('legalFirstName')}
/>
this.clearErrorAndSetValue('legalLastName', val)}
- value={this.props.walletAdditionalDetailsDraft.legalLastName || ''}
+ value={this.props.walletAdditionalDetailsDraft.legalLastName || lastName}
errorText={this.getErrorText('legalLastName')}
/>
;
}
- const currentStep = this.props.userWallet.currentStep || CONST.WALLET.STEP.ONFIDO;
+ if (this.props.userWallet.shouldShowFailedKYC) {
+ return (
+
+
+ Navigation.dismissModal()}
+ />
+
+
+
+ );
+ }
+
+ const currentStep = this.props.userWallet.currentStep || CONST.WALLET.STEP.ADDITIONAL_DETAILS;
+
return (
- {currentStep === CONST.WALLET.STEP.ONFIDO && }
- {currentStep === CONST.WALLET.STEP.ADDITIONAL_DETAILS && }
+ {currentStep === CONST.WALLET.STEP.ADDITIONAL_DETAILS && }
+ {currentStep === CONST.WALLET.STEP.ONFIDO && }
{currentStep === CONST.WALLET.STEP.TERMS && }
{currentStep === CONST.WALLET.STEP.ACTIVATE && }
@@ -47,12 +69,18 @@ class EnablePaymentsPage extends React.Component {
EnablePaymentsPage.propTypes = propTypes;
EnablePaymentsPage.defaultProps = defaultProps;
-export default withOnyx({
- userWallet: {
- key: ONYXKEYS.USER_WALLET,
+export default compose(
+ withLocalize,
+ withOnyx({
+ userWallet: {
+ key: ONYXKEYS.USER_WALLET,
- // We want to refresh the wallet each time the user attempts to activate the wallet so we won't use the
- // stored values here.
- initWithStoredValues: false,
- },
-})(EnablePaymentsPage);
+ // We want to refresh the wallet each time the user attempts to activate the wallet so we won't use the
+ // stored values here.
+ initWithStoredValues: false,
+ },
+ walletAdditionalDetailsDraft: {
+ key: ONYXKEYS.WALLET_ADDITIONAL_DETAILS_DRAFT,
+ },
+ }),
+)(EnablePaymentsPage);
diff --git a/src/pages/EnablePayments/OnfidoPrivacy.js b/src/pages/EnablePayments/OnfidoPrivacy.js
new file mode 100644
index 000000000000..c65b82ae1fa1
--- /dev/null
+++ b/src/pages/EnablePayments/OnfidoPrivacy.js
@@ -0,0 +1,134 @@
+import React from 'react';
+import {View} from 'react-native';
+import lodashGet from 'lodash/get';
+import _ from 'underscore';
+import {withOnyx} from 'react-native-onyx';
+import FullscreenLoadingIndicator from '../../components/FullscreenLoadingIndicator';
+import ONYXKEYS from '../../ONYXKEYS';
+import * as BankAccounts from '../../libs/actions/BankAccounts';
+import styles from '../../styles/styles';
+import TextLink from '../../components/TextLink';
+import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
+import compose from '../../libs/compose';
+import Text from '../../components/Text';
+import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButton';
+import FormScrollView from '../../components/FormScrollView';
+import walletAdditionalDetailsDraftPropTypes from './walletAdditionalDetailsDraftPropTypes';
+import walletOnfidoDataPropTypes from './walletOnfidoDataPropTypes';
+import * as Localize from '../../libs/Localize';
+
+const propTypes = {
+ /** Stores various information used to build the UI and call any APIs */
+ walletOnfidoData: walletOnfidoDataPropTypes,
+
+ /** Stores the personal details typed by the user */
+ walletAdditionalDetailsDraft: walletAdditionalDetailsDraftPropTypes.isRequired,
+
+ ...withLocalizePropTypes,
+};
+
+const defaultProps = {
+ walletOnfidoData: {
+ applicantID: '',
+ sdkToken: '',
+ loading: false,
+ error: '',
+ hasAcceptedPrivacyPolicy: false,
+ },
+};
+
+class OnfidoPrivacy extends React.Component {
+ constructor(props) {
+ super(props);
+
+ this.fetchOnfidoToken = this.fetchOnfidoToken.bind(this);
+ }
+
+ fetchOnfidoToken() {
+ BankAccounts.fetchOnfidoToken(
+ this.props.walletAdditionalDetailsDraft.legalFirstName,
+ this.props.walletAdditionalDetailsDraft.legalLastName,
+ this.props.walletAdditionalDetailsDraft.dob,
+ );
+ }
+
+ render() {
+ let onfidoError = lodashGet(this.props, 'walletOnfidoData.error') || '';
+ if (!onfidoError) {
+ const onfidoFixableErrors = lodashGet(this.props, 'userWallet.onfidoFixableErrors', []);
+ if (!_.isEmpty(onfidoFixableErrors)) {
+ const supportedErrorKeys = ['originalDocumentNeeded', 'documentNeedsBetterQuality', 'imageNeedsBetterQuality', 'selfieIssue', 'selfieNotMatching', 'selfieNotLive'];
+ const translatedFixableErrors = _.filter(_.map(onfidoFixableErrors, (errorKey) => {
+ if (_.contains(supportedErrorKeys, errorKey)) {
+ return Localize.translateLocal(`onfidoStep.${errorKey}`);
+ }
+ return null;
+ }));
+ if (!_.isEmpty(translatedFixableErrors)) {
+ onfidoError = translatedFixableErrors.join(' ');
+ }
+ }
+ }
+
+ return (
+
+ {!this.props.walletOnfidoData.hasAcceptedPrivacyPolicy ? (
+ this.form = el}>
+
+
+ {this.props.translate('onfidoStep.acceptTerms')}
+
+ {this.props.translate('onfidoStep.facialScan')}
+
+ {', '}
+
+ {this.props.translate('common.privacyPolicy')}
+
+ {` ${this.props.translate('common.and')} `}
+
+ {this.props.translate('common.termsOfService')}
+
+ .
+
+
+ {
+ this.form.scrollTo({y: 0, animated: true});
+ }}
+ message={onfidoError}
+ isLoading={this.props.walletOnfidoData.loading}
+ buttonText={onfidoError ? this.props.translate('onfidoStep.tryAgain') : this.props.translate('common.continue')}
+ />
+
+ ) : null}
+ {this.props.walletOnfidoData.hasAcceptedPrivacyPolicy && this.props.walletOnfidoData.loading ? : null}
+
+ );
+ }
+}
+
+OnfidoPrivacy.propTypes = propTypes;
+OnfidoPrivacy.defaultProps = defaultProps;
+
+export default compose(
+ withLocalize,
+ withOnyx({
+ walletOnfidoData: {
+ key: ONYXKEYS.WALLET_ONFIDO,
+
+ // Let's get a new onfido token each time the user hits this flow (as it should only be once)
+ initWithStoredValues: false,
+ },
+ userWallet: {
+ key: ONYXKEYS.USER_WALLET,
+ },
+ }),
+)(OnfidoPrivacy);
diff --git a/src/pages/EnablePayments/OnfidoStep.js b/src/pages/EnablePayments/OnfidoStep.js
index e3ef5fe3beb7..16ea1f897bcc 100644
--- a/src/pages/EnablePayments/OnfidoStep.js
+++ b/src/pages/EnablePayments/OnfidoStep.js
@@ -1,41 +1,26 @@
import React from 'react';
-import {View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
-import PropTypes from 'prop-types';
+import lodashGet from 'lodash/get';
import Onfido from '../../components/Onfido';
-import FullscreenLoadingIndicator from '../../components/FullscreenLoadingIndicator';
import ONYXKEYS from '../../ONYXKEYS';
import * as BankAccounts from '../../libs/actions/BankAccounts';
import Navigation from '../../libs/Navigation/Navigation';
import CONST from '../../CONST';
-import Button from '../../components/Button';
import HeaderWithCloseButton from '../../components/HeaderWithCloseButton';
-import styles from '../../styles/styles';
-import TextLink from '../../components/TextLink';
+import * as Wallet from '../../libs/actions/Wallet';
import withLocalize, {withLocalizePropTypes} from '../../components/withLocalize';
import compose from '../../libs/compose';
-import Text from '../../components/Text';
import Growl from '../../libs/Growl';
+import OnfidoPrivacy from './OnfidoPrivacy';
+import walletAdditionalDetailsDraftPropTypes from './walletAdditionalDetailsDraftPropTypes';
+import walletOnfidoDataPropTypes from './walletOnfidoDataPropTypes';
const propTypes = {
/** Stores various information used to build the UI and call any APIs */
- walletOnfidoData: PropTypes.shape({
+ walletOnfidoData: walletOnfidoDataPropTypes,
- /** Unique identifier returned from fetchOnfidoToken then re-sent to ActivateWallet with Onfido response data */
- applicantID: PropTypes.string,
-
- /** Token used to initialize the Onfido SDK token */
- sdkToken: PropTypes.string,
-
- /** Loading state to provide feedback when we are waiting for a request to finish */
- loading: PropTypes.bool,
-
- /** Error message to inform the user of any problem that might occur */
- error: PropTypes.string,
-
- /** Whether the user has accepted the privacy policy of Onfido or not */
- hasAcceptedPrivacyPolicy: PropTypes.bool,
- }),
+ /** Stores the personal details typed by the user */
+ walletAdditionalDetailsDraft: walletAdditionalDetailsDraftPropTypes.isRequired,
...withLocalizePropTypes,
};
@@ -48,6 +33,17 @@ const defaultProps = {
};
class OnfidoStep extends React.Component {
+ componentDidMount() {
+ // Once in Onfido step, if we somehow don't have the personal info, go back to previous step, as we need them for Onfido{
+ const firstName = lodashGet(this.props, 'walletAdditionalDetailsDraft.legalFirstName');
+ const lastName = lodashGet(this.props, 'walletAdditionalDetailsDraft.legalLastName');
+ const dob = lodashGet(this.props, 'walletAdditionalDetailsDraft.dob');
+
+ if (!firstName || !lastName || !dob) {
+ Wallet.updateCurrentStep(CONST.WALLET.STEP.ADDITIONAL_DETAILS);
+ }
+ }
+
/**
* @returns {boolean|*}
*/
@@ -65,7 +61,7 @@ class OnfidoStep extends React.Component {
title={this.props.translate('onfidoStep.verifyIdentity')}
onCloseButtonPress={() => Navigation.dismissModal()}
shouldShowBackButton
- onBackButtonPress={() => Navigation.goBack()}
+ onBackButtonPress={() => Wallet.updateCurrentStep(CONST.WALLET.STEP.ADDITIONAL_DETAILS)}
/>
{
this.canShowOnfido() ? (
@@ -87,60 +83,7 @@ class OnfidoStep extends React.Component {
}}
/>
) : (
-
- {!this.props.walletOnfidoData.hasAcceptedPrivacyPolicy && (
- <>
-
-
- {this.props.translate('onfidoStep.acceptTerms')}
-
- {this.props.translate('onfidoStep.facialScan')}
-
- {', '}
-
- {this.props.translate('common.privacyPolicy')}
-
- {` ${this.props.translate('common.and')} `}
-
- {this.props.translate('common.termsOfService')}
-
- .
-
-
-
+
)
}
>
diff --git a/src/pages/EnablePayments/userWalletPropTypes.js b/src/pages/EnablePayments/userWalletPropTypes.js
index 6c43089fa1de..9cefeab81a2f 100644
--- a/src/pages/EnablePayments/userWalletPropTypes.js
+++ b/src/pages/EnablePayments/userWalletPropTypes.js
@@ -8,5 +8,8 @@ export default {
/** Status of wallet - e.g. SILVER or GOLD */
tierName: PropTypes.string,
+
+ /** If we should show the FailedKYC view after the user submitted their info with a non fixable error */
+ shouldShowFailedKYC: PropTypes.bool,
}),
};
diff --git a/src/pages/EnablePayments/walletAdditionalDetailsDraftPropTypes.js b/src/pages/EnablePayments/walletAdditionalDetailsDraftPropTypes.js
new file mode 100644
index 000000000000..747fa82f9fa3
--- /dev/null
+++ b/src/pages/EnablePayments/walletAdditionalDetailsDraftPropTypes.js
@@ -0,0 +1,13 @@
+import PropTypes from 'prop-types';
+
+export default PropTypes.shape({
+ legalFirstName: PropTypes.string,
+ legalLastName: PropTypes.string,
+ addressStreet: PropTypes.string,
+ addressCity: PropTypes.string,
+ addressState: PropTypes.string,
+ addressZip: PropTypes.string,
+ phoneNumber: PropTypes.string,
+ dob: PropTypes.string,
+ ssn: PropTypes.string,
+});
diff --git a/src/pages/EnablePayments/walletOnfidoDataPropTypes.js b/src/pages/EnablePayments/walletOnfidoDataPropTypes.js
new file mode 100644
index 000000000000..f2dcf3d4edf1
--- /dev/null
+++ b/src/pages/EnablePayments/walletOnfidoDataPropTypes.js
@@ -0,0 +1,18 @@
+import PropTypes from 'prop-types';
+
+export default PropTypes.shape({
+ /** Unique identifier returned from fetchOnfidoToken then re-sent to ActivateWallet with Onfido response data */
+ applicantID: PropTypes.string,
+
+ /** Token used to initialize the Onfido SDK token */
+ sdkToken: PropTypes.string,
+
+ /** Loading state to provide feedback when we are waiting for a request to finish */
+ loading: PropTypes.bool,
+
+ /** Error message to inform the user of any problem that might occur */
+ error: PropTypes.string,
+
+ /** Whether the user has accepted the privacy policy of Onfido or not */
+ hasAcceptedPrivacyPolicy: PropTypes.bool,
+});
diff --git a/src/pages/RequestCallPage.js b/src/pages/RequestCallPage.js
index 6f73e70fc248..8e340c5465b2 100644
--- a/src/pages/RequestCallPage.js
+++ b/src/pages/RequestCallPage.js
@@ -95,7 +95,7 @@ const defaultProps = {
class RequestCallPage extends Component {
constructor(props) {
super(props);
- const {firstName, lastName} = this.getFirstAndLastName(props.myPersonalDetails);
+ const {firstName, lastName} = PersonalDetails.extractFirstAndLastNameFromAvailableDetails(props.myPersonalDetails);
this.state = {
firstName,
hasFirstNameError: false,
@@ -112,7 +112,6 @@ class RequestCallPage extends Component {
this.getPhoneNumber = this.getPhoneNumber.bind(this);
this.getPhoneNumberError = this.getPhoneNumberError.bind(this);
this.getPhoneExtensionError = this.getPhoneExtensionError.bind(this);
- this.getFirstAndLastName = this.getFirstAndLastName.bind(this);
this.validateInputs = this.validateInputs.bind(this);
this.validatePhoneInput = this.validatePhoneInput.bind(this);
this.validatePhoneExtensionInput = this.validatePhoneExtensionInput.bind(this);
@@ -194,42 +193,6 @@ class RequestCallPage extends Component {
return '';
}
- /**
- * Gets the first and last name from the user's personal details.
- * If the login is the same as the displayName, then they don't exist,
- * so we return empty strings instead.
- * @param {String} login
- * @param {String} displayName
- * @param {String} firstName
- * @param {String} lastName
- *
- * @returns {Object}
- */
- getFirstAndLastName({
- login,
- displayName,
- firstName,
- lastName,
- }) {
- if (firstName || lastName) {
- return {firstName: firstName || '', lastName: lastName || ''};
- }
- if (Str.removeSMSDomain(login) === displayName) {
- return {firstName: '', lastName: ''};
- }
-
- const firstSpaceIndex = displayName.indexOf(' ');
- const lastSpaceIndex = displayName.lastIndexOf(' ');
- if (firstSpaceIndex === -1) {
- return {firstName: displayName, lastName: ''};
- }
-
- return {
- firstName: displayName.substring(0, firstSpaceIndex).trim(),
- lastName: displayName.substring(lastSpaceIndex).trim(),
- };
- }
-
getWaitTimeMessageKey(minutes) {
if (minutes == null) {
return 'requestCallPage.waitTime.calculating';
diff --git a/src/pages/personalDetailsPropType.js b/src/pages/personalDetailsPropType.js
index cab14c111ccc..43bfe5e61261 100644
--- a/src/pages/personalDetailsPropType.js
+++ b/src/pages/personalDetailsPropType.js
@@ -1,6 +1,12 @@
import PropTypes from 'prop-types';
export default PropTypes.shape({
+ // First name of the current user from their personal details
+ firstName: PropTypes.string,
+
+ // Last name of the current user from their personal details
+ lastName: PropTypes.string,
+
// Display name of the current user from their personal details
displayName: PropTypes.string,