diff --git a/app/src/hooks/useSumsubLauncher.ts b/app/src/hooks/useSumsubLauncher.ts index 30d4975ae..a44a19dbe 100644 --- a/app/src/hooks/useSumsubLauncher.ts +++ b/app/src/hooks/useSumsubLauncher.ts @@ -24,9 +24,11 @@ export interface UseSumsubLauncherOptions { */ errorSource: FallbackErrorSource; /** - * Optional callback to handle successful verification + * Optional callback to handle successful verification. + * Receives the Sumsub result and the userId from the access token. + * If not provided, defaults to navigating to KycSuccess with the userId. */ - onSuccess?: (result: SumsubResult) => void | Promise; + onSuccess?: (result: SumsubResult, userId: string) => void | Promise; /** * Optional callback to handle user cancellation */ @@ -96,8 +98,12 @@ export const useSumsubLauncher = (options: UseSumsubLauncherOptions) => { return; } - // Handle success - await onSuccess?.(result); + // Handle success - navigate to KycSuccess by default + if (onSuccess) { + await onSuccess(result, accessToken.userId); + } else { + navigation.navigate('KycSuccess', { userId: accessToken.userId }); + } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); diff --git a/app/src/screens/dev/DevSettingsScreen.tsx b/app/src/screens/dev/DevSettingsScreen.tsx index db5513d9f..48f52f31d 100644 --- a/app/src/screens/dev/DevSettingsScreen.tsx +++ b/app/src/screens/dev/DevSettingsScreen.tsx @@ -41,8 +41,6 @@ const DevSettingsScreen: React.FC = () => { const setLoggingSeverity = useSettingStore(state => state.setLoggingSeverity); const useStrongBox = useSettingStore(state => state.useStrongBox); const setUseStrongBox = useSettingStore(state => state.setUseStrongBox); - const kycEnabled = useSettingStore(state => state.kycEnabled); - const setKycEnabled = useSettingStore(state => state.setKycEnabled); // Custom hooks const { hasNotificationPermission, subscribedTopics, handleTopicToggle } = @@ -98,8 +96,6 @@ const DevSettingsScreen: React.FC = () => { {IS_DEV_MODE && ( diff --git a/app/src/screens/dev/sections/DevTogglesSection.tsx b/app/src/screens/dev/sections/DevTogglesSection.tsx index 0c2972b6c..5763fbeba 100644 --- a/app/src/screens/dev/sections/DevTogglesSection.tsx +++ b/app/src/screens/dev/sections/DevTogglesSection.tsx @@ -10,15 +10,11 @@ import { ParameterSection } from '@/screens/dev/components/ParameterSection'; import { TopicToggleButton } from '@/screens/dev/components/TopicToggleButton'; interface DevTogglesSectionProps { - kycEnabled: boolean; - setKycEnabled: (enabled: boolean) => void; useStrongBox: boolean; setUseStrongBox: (useStrongBox: boolean) => void; } export const DevTogglesSection: React.FC = ({ - kycEnabled, - setKycEnabled, useStrongBox, setUseStrongBox, }) => { @@ -44,11 +40,6 @@ export const DevTogglesSection: React.FC = ({ title="Options" description="Development and security options" > - setKycEnabled(!kycEnabled)} - /> {Platform.OS === 'android' && ( { useNavigation>(); const route = useRoute(); const { trackEvent } = useSelfClient(); - const kycEnabled = useSettingStore(state => state.kycEnabled); const errorType = route.params?.errorType || 'general'; const { title, description } = getErrorMessages(errorType); @@ -82,9 +80,6 @@ const AadhaarUploadErrorScreen: React.FC = () => { onError: () => { // Stay on this screen - user can try again }, - onSuccess: () => { - // Success - provider handles its own success UI - }, }, ); @@ -216,44 +211,40 @@ const AadhaarUploadErrorScreen: React.FC = () => { paddingBottom={paddingBottom} gap={10} > - {kycEnabled && ( - <> - {/* Secondary Button - White fill, black text, rounded */} - + {/* Secondary Button - White fill, black text, rounded */} + - {/* Footer Text - Not italic */} - - Registering with alternative methods may take longer to verify - your document. - - - )} + {/* Footer Text - Not italic */} + + Registering with alternative methods may take longer to verify your + document. + ); diff --git a/app/src/screens/documents/scanning/DocumentCameraTroubleScreen.tsx b/app/src/screens/documents/scanning/DocumentCameraTroubleScreen.tsx index a0a23c2f1..384c8dbfb 100644 --- a/app/src/screens/documents/scanning/DocumentCameraTroubleScreen.tsx +++ b/app/src/screens/documents/scanning/DocumentCameraTroubleScreen.tsx @@ -20,7 +20,6 @@ import useHapticNavigation from '@/hooks/useHapticNavigation'; import { useSumsubLauncher } from '@/hooks/useSumsubLauncher'; import SimpleScrolledTitleLayout from '@/layouts/SimpleScrolledTitleLayout'; import { flush as flushAnalytics } from '@/services/analytics'; -import { useSettingStore } from '@/stores/settingStore'; const tips: TipProps[] = [ { @@ -55,7 +54,6 @@ const DocumentCameraTroubleScreen: React.FC = () => { const selfClient = useSelfClient(); const { useMRZStore } = selfClient; const { countryCode } = useMRZStore(); - const kycEnabled = useSettingStore(state => state.kycEnabled); const { launchSumsubVerification, isLoading } = useSumsubLauncher({ countryCode, errorSource: 'mrz_scan_failed', @@ -82,25 +80,21 @@ const DocumentCameraTroubleScreen: React.FC = () => { page quickly and clearly! - {kycEnabled && ( - <> - - Or try an alternative verification method: - + + Or try an alternative verification method: + - - {isLoading ? 'Loading...' : 'Try Alternative Verification'} - - - )} + + {isLoading ? 'Loading...' : 'Try Alternative Verification'} + } > diff --git a/app/src/screens/documents/scanning/DocumentNFCTroubleScreen.tsx b/app/src/screens/documents/scanning/DocumentNFCTroubleScreen.tsx index 8636754ee..041006044 100644 --- a/app/src/screens/documents/scanning/DocumentNFCTroubleScreen.tsx +++ b/app/src/screens/documents/scanning/DocumentNFCTroubleScreen.tsx @@ -21,7 +21,6 @@ import { selectionChange } from '@/integrations/haptics'; import SimpleScrolledTitleLayout from '@/layouts/SimpleScrolledTitleLayout'; import { flushAllAnalytics } from '@/services/analytics'; import { openSupportForm, SUPPORT_FORM_BUTTON_TEXT } from '@/services/support'; -import { useSettingStore } from '@/stores/settingStore'; const tips: TipProps[] = [ { @@ -62,7 +61,6 @@ const DocumentNFCTroubleScreen: React.FC = () => { const selfClient = useSelfClient(); const { useMRZStore } = selfClient; const { countryCode } = useMRZStore(); - const kycEnabled = useSettingStore(state => state.kycEnabled); const { launchSumsubVerification, isLoading } = useSumsubLauncher({ countryCode, errorSource: 'nfc_scan_failed', @@ -97,16 +95,14 @@ const DocumentNFCTroubleScreen: React.FC = () => { {SUPPORT_FORM_BUTTON_TEXT} - {kycEnabled && ( - - {isLoading ? 'Loading...' : 'Try Alternative Verification'} - - )} + + {isLoading ? 'Loading...' : 'Try Alternative Verification'} + } > diff --git a/app/src/screens/documents/scanning/RegistrationFallbackMRZScreen.tsx b/app/src/screens/documents/scanning/RegistrationFallbackMRZScreen.tsx index bcab71bf2..03b34e50f 100644 --- a/app/src/screens/documents/scanning/RegistrationFallbackMRZScreen.tsx +++ b/app/src/screens/documents/scanning/RegistrationFallbackMRZScreen.tsx @@ -28,7 +28,6 @@ import { NavBar } from '@/components/navbar/BaseNavBar'; import { useSumsubLauncher } from '@/hooks/useSumsubLauncher'; import { buttonTap } from '@/integrations/haptics'; import type { RootStackParamList } from '@/navigation'; -import { useSettingStore } from '@/stores/settingStore'; import { extraYPadding } from '@/utils/styleUtils'; type RegistrationFallbackMRZRouteParams = { @@ -61,7 +60,6 @@ const RegistrationFallbackMRZScreen: React.FC = () => { const { trackEvent, useMRZStore } = selfClient; const storeCountryCode = useMRZStore(state => state.countryCode); const documentType = useMRZStore(state => state.documentType); - const kycEnabled = useSettingStore(state => state.kycEnabled); // Use country code from route params, or fall back to MRZ store const countryCode = route.params?.countryCode || storeCountryCode || ''; @@ -79,10 +77,6 @@ const RegistrationFallbackMRZScreen: React.FC = () => { // Stay on this screen - user can try again // Error is already logged in the hook }, - onSuccess: () => { - // Success - provider handles its own success UI - // The screen will be navigated away by the provider's flow - }, }, ); @@ -216,44 +210,40 @@ const RegistrationFallbackMRZScreen: React.FC = () => { paddingBottom={paddingBottom} gap={10} > - {kycEnabled && ( - <> - {/* Secondary Button - White fill, black text, rounded */} - + {/* Secondary Button - White fill, black text, rounded */} + - {/* Footer Text - Not italic */} - - Registering with alternative methods may take longer to verify - your document. - - - )} + {/* Footer Text - Not italic */} + + Registering with alternative methods may take longer to verify your + document. + ); diff --git a/app/src/screens/documents/scanning/RegistrationFallbackNFCScreen.tsx b/app/src/screens/documents/scanning/RegistrationFallbackNFCScreen.tsx index a72d277f6..00e681555 100644 --- a/app/src/screens/documents/scanning/RegistrationFallbackNFCScreen.tsx +++ b/app/src/screens/documents/scanning/RegistrationFallbackNFCScreen.tsx @@ -29,7 +29,6 @@ import { NavBar } from '@/components/navbar/BaseNavBar'; import { useSumsubLauncher } from '@/hooks/useSumsubLauncher'; import { buttonTap } from '@/integrations/haptics'; import type { RootStackParamList } from '@/navigation'; -import { useSettingStore } from '@/stores/settingStore'; import { extraYPadding } from '@/utils/styleUtils'; type RegistrationFallbackNFCRouteParams = { @@ -62,7 +61,6 @@ const RegistrationFallbackNFCScreen: React.FC = () => { const { trackEvent, useMRZStore } = selfClient; const storeCountryCode = useMRZStore(state => state.countryCode); const documentType = useMRZStore(state => state.documentType); - const kycEnabled = useSettingStore(state => state.kycEnabled); // Use country code from route params, or fall back to MRZ store const countryCode = route.params?.countryCode || storeCountryCode || ''; @@ -80,10 +78,6 @@ const RegistrationFallbackNFCScreen: React.FC = () => { // Stay on this screen - user can try again // Error is already logged in the hook }, - onSuccess: () => { - // Success - provider handles its own success UI - // The screen will be navigated away by the provider's flow - }, }, ); @@ -242,44 +236,40 @@ const RegistrationFallbackNFCScreen: React.FC = () => { paddingBottom={paddingBottom} gap={10} > - {kycEnabled && ( - <> - {/* Secondary Button - White fill, black text, rounded */} - + {/* Secondary Button - White fill, black text, rounded */} + - {/* Footer Text - Not italic */} - - Registering with alternative methods may take longer to verify - your document. - - - )} + {/* Footer Text - Not italic */} + + Registering with alternative methods may take longer to verify your + document. + ); diff --git a/app/src/screens/documents/selection/IDPickerScreen.tsx b/app/src/screens/documents/selection/IDPickerScreen.tsx index f3164f34d..3d8415110 100644 --- a/app/src/screens/documents/selection/IDPickerScreen.tsx +++ b/app/src/screens/documents/selection/IDPickerScreen.tsx @@ -13,7 +13,6 @@ import IDSelection from '@selfxyz/mobile-sdk-alpha/onboarding/id-selection-scree import { DocumentFlowNavBar } from '@/components/navbar/DocumentFlowNavBar'; import type { RootStackParamList } from '@/navigation'; -import { useSettingStore } from '@/stores/settingStore'; import { extraYPadding } from '@/utils/styleUtils'; type IDPickerScreenRouteProp = RouteProp; @@ -22,7 +21,6 @@ const IDPickerScreen: React.FC = () => { const route = useRoute(); const { countryCode = '', documentTypes = [] } = route.params || {}; const bottom = useSafeAreaInsets().bottom; - const kycEnabled = useSettingStore(state => state.kycEnabled); return ( { paddingBottom={bottom + extraYPadding + 24} > - + ); }; diff --git a/app/src/screens/documents/selection/LogoConfirmationScreen.tsx b/app/src/screens/documents/selection/LogoConfirmationScreen.tsx index 10c7a4ee2..916ee9b91 100644 --- a/app/src/screens/documents/selection/LogoConfirmationScreen.tsx +++ b/app/src/screens/documents/selection/LogoConfirmationScreen.tsx @@ -33,7 +33,6 @@ import { import { ExpandableBottomLayout } from '@/layouts/ExpandableBottomLayout'; import type { RootStackParamList } from '@/navigation'; import { useFeedback } from '@/providers/feedbackProvider'; -import { useSettingStore } from '@/stores/settingStore'; type LogoConfirmationScreenRouteProp = RouteProp< RootStackParamList, @@ -47,7 +46,6 @@ const LogoConfirmationScreen: React.FC = () => { useNavigation>(); const { showModal } = useFeedback(); const navigateToOnboarding = useHapticNavigation('DocumentOnboarding'); - const kycEnabled = useSettingStore(state => state.kycEnabled); const handleConfirm = useCallback(() => { buttonTap(); @@ -72,12 +70,27 @@ const LogoConfirmationScreen: React.FC = () => { }); // User cancelled/dismissed without completing verification - const cancelledStatuses = ['Initial', 'Incomplete', 'Interrupted']; - if (cancelledStatuses.includes(result.status)) { + if ( + !result.success && + ['Initial', 'Incomplete', 'Interrupted'].includes(result.status) + ) { return; } - // User completed verification - navigate to KycSuccessScreen + // Verification failed (provider error/rejection) + if (!result.success) { + console.error( + 'Sumsub verification failed:', + result.errorType ?? result.status, + ); + navigation.navigate('KycFailure', { + countryCode, + canRetry: true, + }); + return; + } + + // Verification succeeded - navigate to KycSuccessScreen navigation.navigate('KycSuccess', { userId: accessToken.userId }); } catch { console.error('Error launching Sumsub verification'); @@ -138,9 +151,7 @@ const LogoConfirmationScreen: React.FC = () => { Yes - {kycEnabled && ( - No - )} + No diff --git a/app/src/stores/settingStore.ts b/app/src/stores/settingStore.ts index abecfc444..eee144d61 100644 --- a/app/src/stores/settingStore.ts +++ b/app/src/stores/settingStore.ts @@ -21,7 +21,6 @@ interface PersistedSettingsState { homeScreenViewCount: number; incrementHomeScreenViewCount: () => void; isDevMode: boolean; - kycEnabled: boolean; loggingSeverity: LoggingSeverity; pointsAddress: string | null; removeSubscribedTopic: (topic: string) => void; @@ -33,7 +32,6 @@ interface PersistedSettingsState { setFcmToken: (token: string | null) => void; setHasViewedRecoveryPhrase: (viewed: boolean) => void; setKeychainMigrationCompleted: () => void; - setKycEnabled: (enabled: boolean) => void; setLoggingSeverity: (severity: LoggingSeverity) => void; setPointsAddress: (address: string | null) => void; setSkipDocumentSelector: (value: boolean) => void; @@ -150,10 +148,6 @@ export const useSettingStore = create()( useStrongBox: false, setUseStrongBox: (useStrongBox: boolean) => set({ useStrongBox }), - // KYC flow toggle (default: false, dev-only feature) - kycEnabled: false, - setKycEnabled: (enabled: boolean) => set({ kycEnabled: enabled }), - // Non-persisted state (will not be saved to storage) hideNetworkModal: false, setHideNetworkModal: (hideNetworkModal: boolean) => { diff --git a/packages/mobile-sdk-alpha/src/flows/onboarding/id-selection-screen.tsx b/packages/mobile-sdk-alpha/src/flows/onboarding/id-selection-screen.tsx index 4803fff46..9fa2674be 100644 --- a/packages/mobile-sdk-alpha/src/flows/onboarding/id-selection-screen.tsx +++ b/packages/mobile-sdk-alpha/src/flows/onboarding/id-selection-screen.tsx @@ -128,11 +128,10 @@ const DocumentItem: React.FC = ({ docType, onPress }) => { type IDSelectionScreenProps = { countryCode: string; documentTypes: string[]; - showKyc?: boolean; }; const IDSelectionScreen: React.FC = props => { - const { countryCode = '', documentTypes = [], showKyc = false } = props; + const { countryCode = '', documentTypes = [] } = props; const selfClient = useSelfClient(); const onSelectDocumentType = (docType: string) => { @@ -173,11 +172,9 @@ const IDSelectionScreen: React.FC = props => { onSelectDocumentType(docType)} /> ))} Be sure your document is ready to scan - {showKyc && ( - - onSelectDocumentType('kyc')} /> - - )} + + onSelectDocumentType('kyc')} /> + );