diff --git a/CHANGELOG.md b/CHANGELOG.md index 40827fc..9778810 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## next-version +## [5.4.0] - 2022-06-22 + +### Changed: +- Public: +- Public: Update underlying Onfido native SDK versions: + - Android 12.2.0 (up from 11.5.0) + - iOS 25.1.0 (up from 24.6.0) + ## [5.3.0] - 2022-05-02 ### Changed: diff --git a/SampleApp/App.js b/SampleApp/App.js index 044ae76..aa1297b 100644 --- a/SampleApp/App.js +++ b/SampleApp/App.js @@ -12,6 +12,7 @@ export default class App extends Component { message: '--', sdkToken: null, sdkFlowComplete: false, + workflowRunId: null, }; componentDidMount() { @@ -38,6 +39,7 @@ export default class App extends Component { startSDK = () => { Onfido.start({ sdkToken: this.state.sdkToken, + workflowRunId: this.state.workflowRunId, localisation: { ios_strings_file_name: 'Localizable', }, diff --git a/SampleApp/android/app/build.gradle b/SampleApp/android/app/build.gradle index 5d445e6..7b87ec4 100644 --- a/SampleApp/android/app/build.gradle +++ b/SampleApp/android/app/build.gradle @@ -137,7 +137,7 @@ android { } } // TODO: ET-385 Remove this workaround for React 0.62.2 when upgrading to a React 0.63+. - force "com.facebook.soloader:soloader:0.8.2" + force "com.facebook.soloader:soloader:0.9.0+" } } diff --git a/SampleApp/backend-server-example.js b/SampleApp/backend-server-example.js index c707c49..07da3c2 100644 --- a/SampleApp/backend-server-example.js +++ b/SampleApp/backend-server-example.js @@ -3,12 +3,14 @@ * * The applicant must be created in your backend server. The apiToken must never be in code or in * memory of the client code, or nefarious actors will be able to mis-use it. + * If the workflowId is provided, the standard steps will be ovewritten. * * The code below is meant to demo a working integration of the Onfido React Native SDK. */ const createSdkToken = async (applicant, applicationId) => { const apiToken = 'YOUR_API_TOKEN_HERE'; // DO NOT expose your api token in client code: keep it on the backend server. + const workflowId = null; // This is not mandatory for the standard integration, and make sure to keep it on the backend server. const applicantResponse = await fetch( 'https://api.onfido.com/v3/applicants', @@ -82,8 +84,53 @@ const createSdkToken = async (applicant, applicationId) => { sdkToken: null, }; }); + + let workflowRunId; + if (workflowId) { + const workflowRunIdBody = { + workflow_id: workflowId, + applicant_id: sdkRequestBody.applicant_id, + }; + const workflowRunIdResponse = await fetch( + 'https://api.onfido.com/v4/workflow_runs', + { + method: 'POST', + headers: { + Authorization: 'Token token=' + apiToken, + 'Content-Type': 'application/json', + }, + body: JSON.stringify(workflowRunIdBody), + }, + ); + + if (!workflowRunIdResponse.ok) { + console.log(workflowRunIdResponse, 'error'); + return { + status: 'Unable to start the SDK', + message: 'Error retrieving workflow run id from server', + sdkToken: sdkToken, + workflowRunId: null, + }; + } + + await workflowRunIdResponse + .json() + .then((responseJson) => (workflowRunId = responseJson.id)) + .catch((err) => { + console.log(err, 'error'); + return { + status: 'Unable to start the SDK', + message: + 'Unexpected error occurred while trying to get the workflow run id from the response.', + sdkToken: sdkToken, + workflowRunId: null, + }; + }); + } + return { sdkToken, + workflowRunId, }; }; diff --git a/SampleApp/ios/Podfile.lock b/SampleApp/ios/Podfile.lock index 1beb73f..a24d794 100644 --- a/SampleApp/ios/Podfile.lock +++ b/SampleApp/ios/Podfile.lock @@ -11,9 +11,9 @@ PODS: - ReactCommon/turbomodule/core (= 0.67.2) - fmt (6.2.1) - glog (0.3.5) - - Onfido (24.6.0) - - onfido-react-native-sdk (5.2.0): - - Onfido (= 24.6.0) + - Onfido (25.1.0) + - onfido-react-native-sdk (5.3.0): + - Onfido (= 25.1.0) - React - RCT-Folly (2021.06.28.00-v2): - boost @@ -391,8 +391,8 @@ SPEC CHECKSUMS: FBReactNativeSpec: c94002c1d93da3658f4d5119c6994d19961e3d52 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 85ecdd10ee8d8ec362ef519a6a45ff9aa27b2e85 - Onfido: 7b63c00ed1a41574a6d1549d372613b4c01de269 - onfido-react-native-sdk: afb741637b6afb083a790818f46694c2da855ce4 + Onfido: a1645279c7b6ca8de5bb95d27af53c523ffd731c + onfido-react-native-sdk: 6f6e18b2dece6203cba5483fdcf46664b09c8795 RCT-Folly: 803a9cfd78114b2ec0f140cfa6fa2a6bafb2d685 RCTRequired: cd47794163052d2b8318c891a7a14fcfaccc75ab RCTTypeSafety: 393bb40b3e357b224cde53d3fec26813c52428b1 diff --git a/SampleApp/ios/SampleApp.xcodeproj/project.pbxproj b/SampleApp/ios/SampleApp.xcodeproj/project.pbxproj index 83cfadb..4cfd043 100644 --- a/SampleApp/ios/SampleApp.xcodeproj/project.pbxproj +++ b/SampleApp/ios/SampleApp.xcodeproj/project.pbxproj @@ -19,8 +19,8 @@ 3A207E9426EABFB400EEDE01 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3A207E9326EABFB400EEDE01 /* Localizable.strings */; }; 3A9D456A24180E9E0087A331 /* SampleSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A9D456924180E9E0087A331 /* SampleSwift.swift */; }; A27D5C5624FFA363000BDD48 /* colors.json in Resources */ = {isa = PBXBuildFile; fileRef = A27D5C5524FFA363000BDD48 /* colors.json */; }; - C1B45A4424526D86CF3C519B /* libPods-SampleApp-SampleAppTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B313CF74052C683B3E40960 /* libPods-SampleApp-SampleAppTests.a */; }; - FAFD48624DBCDF07D2C16BD4 /* libPods-SampleApp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B8CE159E3962919607C4C98 /* libPods-SampleApp.a */; }; + C8C63452DD504DB8214841D7 /* libPods-SampleApp-SampleAppTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3AE726E9A39C13A8042A8C1 /* libPods-SampleApp-SampleAppTests.a */; }; + F67D0ED0E589493610E5303A /* libPods-SampleApp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 240E86D893AA7E4E44732CC3 /* libPods-SampleApp.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -45,7 +45,6 @@ 00E356EE1AD99517003FC87E /* SampleAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SampleAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 00E356F21AD99517003FC87E /* SampleAppTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleAppTests.m; sourceTree = ""; }; - 05D84D8AD25FE3B107C29C07 /* Pods-SampleApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleApp.debug.xcconfig"; path = "Target Support Files/Pods-SampleApp/Pods-SampleApp.debug.xcconfig"; sourceTree = ""; }; 13B07F961A680F5B00A75B9A /* SampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = SampleApp/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = SampleApp/AppDelegate.m; sourceTree = ""; }; @@ -53,20 +52,19 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = SampleApp/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = SampleApp/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = SampleApp/main.m; sourceTree = ""; }; - 2B313CF74052C683B3E40960 /* libPods-SampleApp-SampleAppTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SampleApp-SampleAppTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 240E86D893AA7E4E44732CC3 /* libPods-SampleApp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SampleApp.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 2D02E47B1E0B4A5D006451C7 /* SampleApp-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SampleApp-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 2D02E4901E0B4A5D006451C7 /* SampleApp-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SampleApp-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; - 354E053B8237E8BC941E5FC4 /* Pods-SampleAppTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleAppTests.debug.xcconfig"; path = "Target Support Files/Pods-SampleAppTests/Pods-SampleAppTests.debug.xcconfig"; sourceTree = ""; }; 3A207E9326EABFB400EEDE01 /* Localizable.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Localizable.strings; path = SampleApp/Localizable.strings; sourceTree = ""; }; 3A9D456924180E9E0087A331 /* SampleSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleSwift.swift; sourceTree = ""; }; - 4839A6550C64DF4884891CC2 /* Pods-SampleApp-SampleAppTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleApp-SampleAppTests.debug.xcconfig"; path = "Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests.debug.xcconfig"; sourceTree = ""; }; - 5AF1FE68B222396981831AEA /* Pods-SampleApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleApp.release.xcconfig"; path = "Target Support Files/Pods-SampleApp/Pods-SampleApp.release.xcconfig"; sourceTree = ""; }; - 8B8CE159E3962919607C4C98 /* libPods-SampleApp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SampleApp.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 5720AA6B20C5B2D87F5440D1 /* Pods-SampleApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleApp.debug.xcconfig"; path = "Target Support Files/Pods-SampleApp/Pods-SampleApp.debug.xcconfig"; sourceTree = ""; }; + 6D7BAE0A65F4937026017B25 /* Pods-SampleApp-SampleAppTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleApp-SampleAppTests.debug.xcconfig"; path = "Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests.debug.xcconfig"; sourceTree = ""; }; + 7C75DAFC2AD9FF23AAAA440F /* Pods-SampleApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleApp.release.xcconfig"; path = "Target Support Files/Pods-SampleApp/Pods-SampleApp.release.xcconfig"; sourceTree = ""; }; A27D5C5524FFA363000BDD48 /* colors.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; name = colors.json; path = SampleApp/colors.json; sourceTree = ""; }; - BD7D4F71ACBEFCDEF85ACD10 /* Pods-SampleAppTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleAppTests.release.xcconfig"; path = "Target Support Files/Pods-SampleAppTests/Pods-SampleAppTests.release.xcconfig"; sourceTree = ""; }; - DE4F8C619053832AE0B2BA32 /* Pods-SampleApp-SampleAppTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleApp-SampleAppTests.release.xcconfig"; path = "Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests.release.xcconfig"; sourceTree = ""; }; + D3AE726E9A39C13A8042A8C1 /* libPods-SampleApp-SampleAppTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SampleApp-SampleAppTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; }; + F8E9892C2FC133BFF0E7C6BD /* Pods-SampleApp-SampleAppTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleApp-SampleAppTests.release.xcconfig"; path = "Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -74,7 +72,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C1B45A4424526D86CF3C519B /* libPods-SampleApp-SampleAppTests.a in Frameworks */, + C8C63452DD504DB8214841D7 /* libPods-SampleApp-SampleAppTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -82,7 +80,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - FAFD48624DBCDF07D2C16BD4 /* libPods-SampleApp.a in Frameworks */, + F67D0ED0E589493610E5303A /* libPods-SampleApp.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -140,8 +138,8 @@ children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, ED2971642150620600B7C4FE /* JavaScriptCore.framework */, - 8B8CE159E3962919607C4C98 /* libPods-SampleApp.a */, - 2B313CF74052C683B3E40960 /* libPods-SampleApp-SampleAppTests.a */, + 240E86D893AA7E4E44732CC3 /* libPods-SampleApp.a */, + D3AE726E9A39C13A8042A8C1 /* libPods-SampleApp-SampleAppTests.a */, ); name = Frameworks; sourceTree = ""; @@ -184,12 +182,10 @@ 9673CF611B9B8BBDA7266A57 /* Pods */ = { isa = PBXGroup; children = ( - 05D84D8AD25FE3B107C29C07 /* Pods-SampleApp.debug.xcconfig */, - 5AF1FE68B222396981831AEA /* Pods-SampleApp.release.xcconfig */, - 354E053B8237E8BC941E5FC4 /* Pods-SampleAppTests.debug.xcconfig */, - BD7D4F71ACBEFCDEF85ACD10 /* Pods-SampleAppTests.release.xcconfig */, - 4839A6550C64DF4884891CC2 /* Pods-SampleApp-SampleAppTests.debug.xcconfig */, - DE4F8C619053832AE0B2BA32 /* Pods-SampleApp-SampleAppTests.release.xcconfig */, + 5720AA6B20C5B2D87F5440D1 /* Pods-SampleApp.debug.xcconfig */, + 7C75DAFC2AD9FF23AAAA440F /* Pods-SampleApp.release.xcconfig */, + 6D7BAE0A65F4937026017B25 /* Pods-SampleApp-SampleAppTests.debug.xcconfig */, + F8E9892C2FC133BFF0E7C6BD /* Pods-SampleApp-SampleAppTests.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -201,12 +197,12 @@ isa = PBXNativeTarget; buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "SampleAppTests" */; buildPhases = ( - 38876773F1493717C81F74C4 /* [CP] Check Pods Manifest.lock */, + C0F6B31F6C98336A5EB9B548 /* [CP] Check Pods Manifest.lock */, 00E356EA1AD99517003FC87E /* Sources */, 00E356EB1AD99517003FC87E /* Frameworks */, 00E356EC1AD99517003FC87E /* Resources */, - F2B7482D3C02D227C1F98FE4 /* [CP] Embed Pods Frameworks */, - 61692A2C2A5A795D4D4D380F /* [CP] Copy Pods Resources */, + 96A511B3AB4EAEFE765013BF /* [CP] Embed Pods Frameworks */, + C32C74B477483ABBC9594CC8 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -222,14 +218,14 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "SampleApp" */; buildPhases = ( - 475043B9054073DC4F7156D7 /* [CP] Check Pods Manifest.lock */, + 0534EECA4D8208F96B37DD93 /* [CP] Check Pods Manifest.lock */, FD10A7F022414F080027D42C /* Start Packager */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - 591ED21D0C540EF2C2053836 /* [CP] Embed Pods Frameworks */, - 8085E483CC895D4264D9A596 /* [CP] Copy Pods Resources */, + 505CFECE4DEFFA90E5358D11 /* [CP] Embed Pods Frameworks */, + F27DDFD572EEF90E2BD8E2DD /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -377,71 +373,67 @@ shellPath = /bin/sh; shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; }; - 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = { + 0534EECA4D8208F96B37DD93 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "Bundle React Native Code And Images"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-SampleApp-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; - 38876773F1493717C81F74C4 /* [CP] Check Pods Manifest.lock */ = { + 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( ); + name = "Bundle React Native Code And Images"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-SampleApp-SampleAppTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; + shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; }; - 475043B9054073DC4F7156D7 /* [CP] Check Pods Manifest.lock */ = { + 505CFECE4DEFFA90E5358D11 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-SampleApp/Pods-SampleApp-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/Onfido/Onfido.framework/Onfido", ); + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-SampleApp-checkManifestLockResult.txt", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Onfido.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SampleApp/Pods-SampleApp-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 591ED21D0C540EF2C2053836 /* [CP] Embed Pods Frameworks */ = { + 96A511B3AB4EAEFE765013BF /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-SampleApp/Pods-SampleApp-frameworks.sh", + "${PODS_ROOT}/Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests-frameworks.sh", "${PODS_XCFRAMEWORKS_BUILD_DIR}/Onfido/Onfido.framework/Onfido", ); name = "[CP] Embed Pods Frameworks"; @@ -450,34 +442,38 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SampleApp/Pods-SampleApp-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 61692A2C2A5A795D4D4D380F /* [CP] Copy Pods Resources */ = { + C0F6B31F6C98336A5EB9B548 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); + inputFileListPaths = ( + ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle", + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( ); - name = "[CP] Copy Pods Resources"; outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle", + "$(DERIVED_FILE_DIR)/Pods-SampleApp-SampleAppTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests-resources.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 8085E483CC895D4264D9A596 /* [CP] Copy Pods Resources */ = { + C32C74B477483ABBC9594CC8 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-SampleApp/Pods-SampleApp-resources.sh", + "${PODS_ROOT}/Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests-resources.sh", "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle", ); name = "[CP] Copy Pods Resources"; @@ -486,25 +482,25 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SampleApp/Pods-SampleApp-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; - F2B7482D3C02D227C1F98FE4 /* [CP] Embed Pods Frameworks */ = { + F27DDFD572EEF90E2BD8E2DD /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/Onfido/Onfido.framework/Onfido", + "${PODS_ROOT}/Target Support Files/Pods-SampleApp/Pods-SampleApp-resources.sh", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle", ); - name = "[CP] Embed Pods Frameworks"; + name = "[CP] Copy Pods Resources"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Onfido.framework", + "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SampleApp-SampleAppTests/Pods-SampleApp-SampleAppTests-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SampleApp/Pods-SampleApp-resources.sh\"\n"; showEnvVarsInLog = 0; }; FD10A7F022414F080027D42C /* Start Packager */ = { @@ -613,7 +609,7 @@ /* Begin XCBuildConfiguration section */ 00E356F61AD99517003FC87E /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4839A6550C64DF4884891CC2 /* Pods-SampleApp-SampleAppTests.debug.xcconfig */; + baseConfigurationReference = 6D7BAE0A65F4937026017B25 /* Pods-SampleApp-SampleAppTests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -637,7 +633,7 @@ }; 00E356F71AD99517003FC87E /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DE4F8C619053832AE0B2BA32 /* Pods-SampleApp-SampleAppTests.release.xcconfig */; + baseConfigurationReference = F8E9892C2FC133BFF0E7C6BD /* Pods-SampleApp-SampleAppTests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -658,7 +654,7 @@ }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 05D84D8AD25FE3B107C29C07 /* Pods-SampleApp.debug.xcconfig */; + baseConfigurationReference = 5720AA6B20C5B2D87F5440D1 /* Pods-SampleApp.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -683,7 +679,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5AF1FE68B222396981831AEA /* Pods-SampleApp.release.xcconfig */; + baseConfigurationReference = 7C75DAFC2AD9FF23AAAA440F /* Pods-SampleApp.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; diff --git a/android/build.gradle b/android/build.gradle index 6798a7c..7f9cd26 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -99,7 +99,7 @@ repositories { dependencies { //noinspection GradleDynamicVersion implementation 'com.facebook.react:react-native:+' // From node_modules - implementation "com.onfido.sdk.capture:onfido-capture-sdk:11.5.0" + implementation "com.onfido.sdk.capture:onfido-capture-sdk:12.2.0" implementation "com.squareup.okhttp3:logging-interceptor:3.8.0" implementation "com.squareup.okhttp3:okhttp:3.8.0" // Fix for crash due to 'java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/swiperefreshlayout/widget/SwipeRefreshLayout;'' diff --git a/android/src/main/java/com/onfido/reactnative/sdk/OnfidoSdkModule.java b/android/src/main/java/com/onfido/reactnative/sdk/OnfidoSdkModule.java index d8ef5c1..90ac623 100644 --- a/android/src/main/java/com/onfido/reactnative/sdk/OnfidoSdkModule.java +++ b/android/src/main/java/com/onfido/reactnative/sdk/OnfidoSdkModule.java @@ -9,23 +9,23 @@ import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.UnexpectedNativeTypeException; - -import java.util.List; -import java.util.ArrayList; - -import com.facebook.react.bridge.Arguments; - -import com.onfido.android.sdk.capture.Onfido; +import com.onfido.android.sdk.capture.DocumentType; import com.onfido.android.sdk.capture.EnterpriseFeatures; -import com.onfido.android.sdk.capture.ui.options.FlowStep; +import com.onfido.android.sdk.capture.Onfido; import com.onfido.android.sdk.capture.OnfidoConfig; import com.onfido.android.sdk.capture.OnfidoFactory; +import com.onfido.android.sdk.capture.errors.EnterpriseFeatureNotEnabledException; +import com.onfido.android.sdk.capture.errors.EnterpriseFeaturesInvalidLogoCobrandingException; import com.onfido.android.sdk.capture.ui.camera.face.FaceCaptureStep; import com.onfido.android.sdk.capture.ui.camera.face.FaceCaptureVariant; -import com.onfido.android.sdk.capture.DocumentType; -import com.onfido.android.sdk.capture.utils.CountryCode; import com.onfido.android.sdk.capture.ui.options.CaptureScreenStep; -import com.onfido.android.sdk.capture.errors.*; +import com.onfido.android.sdk.capture.ui.options.FlowStep; +import com.onfido.android.sdk.capture.utils.CountryCode; +import com.onfido.android.sdk.workflow.OnfidoWorkflow; +import com.onfido.android.sdk.workflow.WorkflowConfig; + +import java.util.ArrayList; +import java.util.List; public class OnfidoSdkModule extends ReactContextBaseJavaModule { @@ -38,7 +38,7 @@ public OnfidoSdkModule(final ReactApplicationContext reactContext) { super(reactContext); this.reactContext = reactContext; this.client = OnfidoFactory.create(reactContext).getClient(); - this.activityEventListener = new OnfidoSdkActivityEventListener(client); + activityEventListener = new OnfidoSdkActivityEventListener(client); reactContext.addActivityEventListener(activityEventListener); } @@ -58,7 +58,9 @@ public String getName() { return "OnfidoSdk"; } - /** NOTE: This indirection is used to allow unit tests to mock this method */ + /** + * NOTE: This indirection is used to allow unit tests to mock this method + */ protected Activity getCurrentActivityInParentClass() { return super.getCurrentActivity(); } @@ -70,10 +72,8 @@ public void start(final ReadableMap config, final Promise promise) { try { final String sdkToken; - final FlowStep[] flowStepsWithOptions; try { sdkToken = getSdkTokenFromConfig(config); - flowStepsWithOptions = getFlowStepsFromConfig(config); } catch (Exception e) { currentPromise.reject("config_error", e); currentPromise = null; @@ -88,58 +88,22 @@ public void start(final ReadableMap config, final Promise promise) { } try { - /* Native SDK seems to have a bug that if an empty EnterpriseFeatures is passed to it, - the logo will still be hidden, even if explicitly set to false */ - EnterpriseFeatures.Builder enterpriseFeaturesBuilder = EnterpriseFeatures.builder(); - boolean hasSetEnterpriseFeatures = false; - - if (getBooleanFromConfig(config, "hideLogo")) { - enterpriseFeaturesBuilder.withHideOnfidoLogo(true); - hasSetEnterpriseFeatures = true; - } else if (getBooleanFromConfig(config, "logoCobrand")) { - int cobrandLogoLight = currentActivity.getApplicationContext().getResources().getIdentifier( - "cobrand_logo_light", - "drawable", - currentActivity.getApplicationContext().getPackageName() - ); - int cobrandLogoDark = currentActivity.getApplicationContext().getResources().getIdentifier( - "cobrand_logo_dark", - "drawable", - currentActivity.getApplicationContext().getPackageName() - ); - if (cobrandLogoLight == 0 || cobrandLogoDark == 0) { - currentPromise.reject("error", new Exception("Cobrand logos were not found")); - currentPromise = null; - return; - } - enterpriseFeaturesBuilder.withCobrandingLogo(cobrandLogoLight, cobrandLogoDark); - hasSetEnterpriseFeatures = true; - } - - OnfidoConfig.Builder onfidoConfigBuilder = OnfidoConfig.builder(currentActivity) - .withSDKToken(sdkToken) - .withCustomFlow(flowStepsWithOptions); + final String workflowRunId = getWorkflowRunIdFromConfig(config); - if (hasSetEnterpriseFeatures) { - onfidoConfigBuilder.withEnterpriseFeatures(enterpriseFeaturesBuilder.build()); + if (!workflowRunId.isEmpty()) { + workflowSDKConfiguration(currentActivity, workflowRunId, sdkToken); + } else { + defaultSDKConfiguration(config, currentActivity, sdkToken); } - - client.startActivityForResult(currentActivity, 1, onfidoConfigBuilder.build()); - } - catch (final EnterpriseFeaturesInvalidLogoCobrandingException e) { + } catch (final EnterpriseFeaturesInvalidLogoCobrandingException e) { currentPromise.reject("error", new EnterpriseFeaturesInvalidLogoCobrandingException()); currentPromise = null; - return; - } - catch (final EnterpriseFeatureNotEnabledException e) { + } catch (final EnterpriseFeatureNotEnabledException e) { currentPromise.reject("error", new EnterpriseFeatureNotEnabledException("logoCobrand")); currentPromise = null; - return; - } - catch (final Exception e) { + } catch (final Exception e) { currentPromise.reject("error", new Exception(e.getMessage(), e)); currentPromise = null; - return; } } catch (final Exception e) { @@ -147,13 +111,64 @@ public void start(final ReadableMap config, final Promise promise) { // Wrap all unexpected exceptions. currentPromise.reject("error", new Exception("Unexpected error starting Onfido page", e)); currentPromise = null; - return; } } + private void workflowSDKConfiguration(Activity currentActivity, String workflowRunId, String sdkToken) { + OnfidoWorkflow.create(currentActivity) + .startActivityForResult(currentActivity, + 1, + new WorkflowConfig.Builder(sdkToken, workflowRunId).build()); + } + + private void defaultSDKConfiguration(final ReadableMap config, Activity currentActivity, String sdkToken) throws Exception { + final FlowStep[] flowStepsWithOptions = getFlowStepsFromConfig(config); + /* Native SDK seems to have a bug that if an empty EnterpriseFeatures is passed to it, + the logo will still be hidden, even if explicitly set to false */ + EnterpriseFeatures.Builder enterpriseFeaturesBuilder = EnterpriseFeatures.builder(); + boolean hasSetEnterpriseFeatures = false; + + if (getBooleanFromConfig(config, "hideLogo")) { + enterpriseFeaturesBuilder.withHideOnfidoLogo(true); + hasSetEnterpriseFeatures = true; + } else if (getBooleanFromConfig(config, "logoCobrand")) { + int cobrandLogoLight = currentActivity.getApplicationContext().getResources().getIdentifier( + "cobrand_logo_light", + "drawable", + currentActivity.getApplicationContext().getPackageName() + ); + int cobrandLogoDark = currentActivity.getApplicationContext().getResources().getIdentifier( + "cobrand_logo_dark", + "drawable", + currentActivity.getApplicationContext().getPackageName() + ); + if (cobrandLogoLight == 0 || cobrandLogoDark == 0) { + currentPromise.reject("error", new Exception("Cobrand logos were not found")); + currentPromise = null; + return; + } + enterpriseFeaturesBuilder.withCobrandingLogo(cobrandLogoLight, cobrandLogoDark); + hasSetEnterpriseFeatures = true; + } + + OnfidoConfig.Builder onfidoConfigBuilder = OnfidoConfig.builder(currentActivity) + .withSDKToken(sdkToken) + .withCustomFlow(flowStepsWithOptions); + + if (hasSetEnterpriseFeatures) { + onfidoConfigBuilder.withEnterpriseFeatures(enterpriseFeaturesBuilder.build()); + } + + client.startActivityForResult(currentActivity, 1, onfidoConfigBuilder.build()); + } + public static String getSdkTokenFromConfig(final ReadableMap config) { - final String sdkToken = config.getString("sdkToken"); - return sdkToken; + return config.getString("sdkToken"); + } + + public static String getWorkflowRunIdFromConfig(final ReadableMap config) { + final String key = "workflowRunId"; + return config.hasKey(key) ? config.getString(key) : ""; } public static FlowStep[] getFlowStepsFromConfig(final ReadableMap config) throws Exception { @@ -196,10 +211,6 @@ public static FlowStep[] getFlowStepsFromConfig(final ReadableMap config) throws flowStepList.add(FlowStep.WELCOME); } - if (userConsentIsIncluded) { - flowStepList.add(FlowStep.USER_CONSENT); - } - if (captureDocumentBoolean != null && captureDocumentBoolean) { flowStepList.add(FlowStep.CAPTURE_DOCUMENT); } else if (captureDocument != null) { @@ -219,7 +230,7 @@ public static FlowStep[] getFlowStepsFromConfig(final ReadableMap config) throws String countryCodeString = captureDocument.getString("alpha2CountryCode"); CountryCode countryCodeEnum = findCountryCodeByAlpha2(countryCodeString); - if (countryCodeEnum ==null) { + if (countryCodeEnum == null) { System.err.println("Unexpected countryCode value: [" + countryCodeString + "]"); throw new Exception("Unexpected countryCode value."); } diff --git a/android/src/main/java/com/onfido/reactnative/sdk/Response.java b/android/src/main/java/com/onfido/reactnative/sdk/Response.java index 126791c..b29ccdd 100644 --- a/android/src/main/java/com/onfido/reactnative/sdk/Response.java +++ b/android/src/main/java/com/onfido/reactnative/sdk/Response.java @@ -14,7 +14,7 @@ public class Document { public Identifiable front; public Identifiable back; } - public class Face extends Identifiable { + public class Face extends Response.Identifiable { public Face(String id, String variant) { super(id); this.variant = variant; @@ -47,4 +47,4 @@ private void initFace(String faceId, String faceVariant) { face = new Face(faceId, faceVariant); } } -} \ No newline at end of file +} diff --git a/ios/OnfidoSdk.swift b/ios/OnfidoSdk.swift index 1547ac5..f2c1534 100644 --- a/ios/OnfidoSdk.swift +++ b/ios/OnfidoSdk.swift @@ -10,7 +10,6 @@ import Foundation import Onfido public class AppearancePublic: NSObject { - public let primaryColor: UIColor public let primaryTitleColor: UIColor public let primaryBackgroundPressedColor: UIColor @@ -23,10 +22,10 @@ public class AppearancePublic: NSObject { primaryBackgroundPressedColor: UIColor, buttonCornerRadius: CGFloat, supportDarkMode: Bool = true) { - self.primaryColor = primaryColor - self.primaryTitleColor = primaryTitleColor - self.primaryBackgroundPressedColor = primaryBackgroundPressedColor - self.buttonCornerRadius = buttonCornerRadius + self.primaryColor = primaryColor + self.primaryTitleColor = primaryTitleColor + self.primaryBackgroundPressedColor = primaryBackgroundPressedColor + self.buttonCornerRadius = buttonCornerRadius self.supportDarkMode = supportDarkMode } } @@ -38,42 +37,42 @@ public class AppearancePublic: NSObject { */ public func loadAppearancePublicFromFile(filePath: String?) throws -> AppearancePublic? { - do { - let jsonResult:Any - do { - guard let path = filePath else { return nil } - let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe) - jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) - } catch let e as NSError where e.code == NSFileNoSuchFileError || e.code == NSFileReadNoSuchFileError { - jsonResult = Dictionary() - } - if let jsonResult = jsonResult as? Dictionary { - let primaryColor: UIColor = (jsonResult["onfidoPrimaryColor"] == nil) - ? UIColor.primaryColor : UIColor.from(hex: jsonResult["onfidoPrimaryColor"] as! String) - let primaryTitleColor: UIColor = (jsonResult["onfidoPrimaryButtonTextColor"] == nil) - ? UIColor.white : UIColor.from(hex: jsonResult["onfidoPrimaryButtonTextColor"] as! String) - let primaryBackgroundPressedColor: UIColor = (jsonResult["onfidoPrimaryButtonColorPressed"] == nil) - ? UIColor.primaryButtonColorPressed : UIColor.from(hex: jsonResult["onfidoPrimaryButtonColorPressed"] as! String) - let buttonCornerRadius: CGFloat = (jsonResult["onfidoIosButtonCornerRadius"] == nil) + do { + let jsonResult:Any + do { + guard let path = filePath else { return nil } + let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe) + jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves) + } catch let e as NSError where e.code == NSFileNoSuchFileError || e.code == NSFileReadNoSuchFileError { + jsonResult = Dictionary() + } + if let jsonResult = jsonResult as? Dictionary { + let primaryColor: UIColor = (jsonResult["onfidoPrimaryColor"] == nil) + ? UIColor.primaryColor : UIColor.from(hex: jsonResult["onfidoPrimaryColor"] as! String) + let primaryTitleColor: UIColor = (jsonResult["onfidoPrimaryButtonTextColor"] == nil) + ? UIColor.white : UIColor.from(hex: jsonResult["onfidoPrimaryButtonTextColor"] as! String) + let primaryBackgroundPressedColor: UIColor = (jsonResult["onfidoPrimaryButtonColorPressed"] == nil) + ? UIColor.primaryButtonColorPressed : UIColor.from(hex: jsonResult["onfidoPrimaryButtonColorPressed"] as! String) + let buttonCornerRadius: CGFloat = (jsonResult["onfidoIosButtonCornerRadius"] == nil) ? 5 : jsonResult["onfidoIosButtonCornerRadius"] as! CGFloat let supportDarkMode: Bool = (jsonResult["onfidoIosSupportDarkMode"] == nil) - ? true : jsonResult["onfidoIosSupportDarkMode"] as! Bool + ? true : jsonResult["onfidoIosSupportDarkMode"] as! Bool - let appearancePublic = AppearancePublic( - primaryColor: primaryColor, - primaryTitleColor: primaryTitleColor, - primaryBackgroundPressedColor: primaryBackgroundPressedColor, + let appearancePublic = AppearancePublic( + primaryColor: primaryColor, + primaryTitleColor: primaryTitleColor, + primaryBackgroundPressedColor: primaryBackgroundPressedColor, buttonCornerRadius: buttonCornerRadius, - supportDarkMode: supportDarkMode - ) - return appearancePublic - } else { - return nil + supportDarkMode: supportDarkMode + ) + return appearancePublic + } else { + return nil + } + } catch let error { + throw NSError(domain: "There was an error setting colors for Appearance: \(error)", code: 0) } - } catch let error { - throw NSError(domain: "There was an error setting colors for Appearance: \(error)", code: 0) - } } /** * Load appearance data from the specified file. If the file cannot be loaded, use the default colors. @@ -94,135 +93,160 @@ public func loadAppearanceFromFile(filePath: String?) throws -> Appearance { } } +public func getSDKToken(from config: NSDictionary) -> String { + return config["sdkToken"] as! String +} + +public func getLocalisationConfigFileName(from config: NSDictionary) -> String? { + guard let localisationConfig = config["localisation"] as? NSDictionary, + let file = localisationConfig["ios_strings_file_name"] as? String + else { return nil } + + return file +} + public func buildOnfidoConfig(config:NSDictionary, appearance: Appearance) throws -> Onfido.OnfidoConfigBuilder { - let sdkToken:String = config["sdkToken"] as! String - let flowSteps:NSDictionary? = config["flowSteps"] as? NSDictionary - let captureDocument:NSDictionary? = flowSteps?["captureDocument"] as? NSDictionary - let captureFace:NSDictionary? = flowSteps?["captureFace"] as? NSDictionary - - var onfidoConfig = OnfidoConfig.builder() - .withSDKToken(sdkToken) - .withAppearance(appearance) - - var enterpriseFeatures = EnterpriseFeatures.builder() - - if let localisationConfig = config["localisation"] as? NSDictionary, let file = localisationConfig["ios_strings_file_name"] as? String { - onfidoConfig = onfidoConfig.withCustomLocalization(andTableName: file) - } - - if flowSteps?["welcome"] as? Bool == true { - onfidoConfig = onfidoConfig.withWelcomeStep() - } - - if flowSteps?["userConsent"] as? Bool == true { - onfidoConfig = onfidoConfig.withUserConsentStep() - } - - if let docType = captureDocument?["docType"] as? String, let countryCode = captureDocument?["countryCode"] as? String { - switch docType { - case "PASSPORT": - onfidoConfig = onfidoConfig.withDocumentStep(ofType: .passport(config: PassportConfiguration())) - case "DRIVING_LICENCE": - onfidoConfig = onfidoConfig.withDocumentStep(ofType: .drivingLicence(config: DrivingLicenceConfiguration(country: countryCode))) - case "NATIONAL_IDENTITY_CARD": - onfidoConfig = onfidoConfig.withDocumentStep(ofType: .nationalIdentityCard(config: NationalIdentityConfiguration(country: countryCode))) - case "RESIDENCE_PERMIT": - onfidoConfig = onfidoConfig.withDocumentStep(ofType: .residencePermit(config: ResidencePermitConfiguration(country: countryCode))) - case "VISA": - onfidoConfig = onfidoConfig.withDocumentStep(ofType: .visa(config: VisaConfiguration(country: countryCode))) - case "WORK_PERMIT": - onfidoConfig = onfidoConfig.withDocumentStep(ofType: .workPermit(config: WorkPermitConfiguration(country: countryCode))) - case "GENERIC": - onfidoConfig = onfidoConfig.withDocumentStep(ofType: .generic(config: GenericDocumentConfiguration(country: countryCode))) - default: - throw NSError(domain: "Unsupported document type", code: 0) + let sdkToken:String = getSDKToken(from: config) + let flowSteps:NSDictionary? = config["flowSteps"] as? NSDictionary + let captureDocument:NSDictionary? = flowSteps?["captureDocument"] as? NSDictionary + let captureFace:NSDictionary? = flowSteps?["captureFace"] as? NSDictionary + + var onfidoConfig = OnfidoConfig.builder() + .withSDKToken(sdkToken) + .withAppearance(appearance) + + let enterpriseFeatures = EnterpriseFeatures.builder() + + if let localisationFile = getLocalisationConfigFileName(from: config) { + onfidoConfig = onfidoConfig.withCustomLocalization(andTableName: localisationFile) } - } else if captureDocument != nil { - onfidoConfig = onfidoConfig.withDocumentStep() - } - - if let faceVariant = captureFace?["type"] as? String { - if faceVariant == "VIDEO" { - onfidoConfig = onfidoConfig.withFaceStep(ofVariant: .video(withConfiguration: VideoStepConfiguration(showIntroVideo: true, manualLivenessCapture: false))) - } else if faceVariant == "PHOTO" { - onfidoConfig = onfidoConfig.withFaceStep(ofVariant: .photo(withConfiguration: nil)) - } else { - throw NSError(domain: "Invalid or unsupported face variant", code: 0) + + if flowSteps?["welcome"] as? Bool == true { + onfidoConfig = onfidoConfig.withWelcomeStep() } - } - if let hideLogo = config["hideLogo"] as? Bool { - enterpriseFeatures.withHideOnfidoLogo(hideLogo) - } + if let docType = captureDocument?["docType"] as? String, let countryCode = captureDocument?["countryCode"] as? String { + switch docType { + case "PASSPORT": + onfidoConfig = onfidoConfig.withDocumentStep(ofType: .passport(config: PassportConfiguration())) + case "DRIVING_LICENCE": + onfidoConfig = onfidoConfig.withDocumentStep(ofType: .drivingLicence(config: DrivingLicenceConfiguration(country: countryCode))) + case "NATIONAL_IDENTITY_CARD": + onfidoConfig = onfidoConfig.withDocumentStep(ofType: .nationalIdentityCard(config: NationalIdentityConfiguration(country: countryCode))) + case "RESIDENCE_PERMIT": + onfidoConfig = onfidoConfig.withDocumentStep(ofType: .residencePermit(config: ResidencePermitConfiguration(country: countryCode))) + case "VISA": + onfidoConfig = onfidoConfig.withDocumentStep(ofType: .visa(config: VisaConfiguration(country: countryCode))) + case "WORK_PERMIT": + onfidoConfig = onfidoConfig.withDocumentStep(ofType: .workPermit(config: WorkPermitConfiguration(country: countryCode))) + case "GENERIC": + onfidoConfig = onfidoConfig.withDocumentStep(ofType: .generic(config: GenericDocumentConfiguration(country: countryCode))) + default: + throw NSError(domain: "Unsupported document type", code: 0) + } + } else if captureDocument != nil { + onfidoConfig = onfidoConfig.withDocumentStep() + } - if config["logoCobrand"] as? Bool == true { - if (UIImage(named: "cobrand-logo-light") != nil && UIImage(named: "cobrand-logo-dark") != nil) { - enterpriseFeatures.withCobrandingLogo(UIImage(named: "cobrand-logo-light")!, cobrandingLogoDarkMode: UIImage(named: "cobrand-logo-dark")!) - } else { - throw NSError(domain: "Cobrand logos were not found", code: 0) + if let faceVariant = captureFace?["type"] as? String { + if faceVariant == "VIDEO" { + onfidoConfig = onfidoConfig.withFaceStep(ofVariant: .video(withConfiguration: VideoStepConfiguration(showIntroVideo: true, manualLivenessCapture: false))) + } else if faceVariant == "PHOTO" { + onfidoConfig = onfidoConfig.withFaceStep(ofVariant: .photo(withConfiguration: nil)) + } else { + throw NSError(domain: "Invalid or unsupported face variant", code: 0) + } } - } - onfidoConfig.withEnterpriseFeatures(enterpriseFeatures.build()) + if let hideLogo = config["hideLogo"] as? Bool { + enterpriseFeatures.withHideOnfidoLogo(hideLogo) + } - return onfidoConfig; + if config["logoCobrand"] as? Bool == true { + if (UIImage(named: "cobrand-logo-light") != nil && UIImage(named: "cobrand-logo-dark") != nil) { + enterpriseFeatures.withCobrandingLogo(UIImage(named: "cobrand-logo-light")!, cobrandingLogoDarkMode: UIImage(named: "cobrand-logo-dark")!) + } else { + throw NSError(domain: "Cobrand logos were not found", code: 0) + } + } + + onfidoConfig.withEnterpriseFeatures(enterpriseFeatures.build()) + return onfidoConfig; +} + +public func buildOnfidoFlow(from config: NSDictionary) throws -> OnfidoFlow { + let appearanceFilePath = Bundle.main.path(forResource: "colors", ofType: "json") + let appearance = try loadAppearanceFromFile(filePath: appearanceFilePath) + let sdkToken = config["sdkToken"] as! String + + if let workflowRunId = config["workflowRunId"] as? String { + let workflowConfig = WorkflowConfiguration(workflowRunId: workflowRunId, sdkToken: sdkToken) + workflowConfig.appearance = appearance + + if let localisationFile = getLocalisationConfigFileName(from: config) { + workflowConfig.localisation = (bundle: Bundle.main, tableName: localisationFile) + } + + return OnfidoFlow(workflowConfiguration: workflowConfig) + } else { + let onfidoConfig = try buildOnfidoConfig(config: config, appearance: appearance) + let builtOnfidoConfig = try onfidoConfig.build() + + return OnfidoFlow(withConfiguration: builtOnfidoConfig) + } } @objc(OnfidoSdk) class OnfidoSdk: NSObject { - @objc static func requiresMainQueueSetup() -> Bool { - return false - } - - @objc func start(_ config: NSDictionary, - resolver resolve: @escaping RCTPromiseResolveBlock, - rejecter reject: @escaping RCTPromiseRejectBlock) -> Void { - DispatchQueue.main.async { - self.run(withConfig: config, resolver: resolve, rejecter: reject) + @objc static func requiresMainQueueSetup() -> Bool { + return false } - } - private func run(withConfig config: NSDictionary, - resolver resolve: @escaping RCTPromiseResolveBlock, - rejecter reject: @escaping RCTPromiseRejectBlock) { + @objc func start(_ config: NSDictionary, + resolver resolve: @escaping RCTPromiseResolveBlock, + rejecter reject: @escaping RCTPromiseRejectBlock) -> Void { + DispatchQueue.main.async { + self.run(withConfig: config, resolver: resolve, rejecter: reject) + } + } - do { - let appearanceFilePath = Bundle.main.path(forResource: "colors", ofType: "json") - let appearance = try loadAppearanceFromFile(filePath: appearanceFilePath) - let onfidoConfig = try buildOnfidoConfig(config: config, appearance: appearance) - let builtOnfidoConfig = try onfidoConfig.build() - - // Copy the face varient from the config since it is not contained in the response: - let flowSteps:NSDictionary? = config["flowSteps"] as? NSDictionary - let captureFace:NSDictionary? = flowSteps?["captureFace"] as? NSDictionary - let faceVariant = captureFace?["type"] as? String - - let onfidoFlow = OnfidoFlow(withConfiguration: builtOnfidoConfig) - .with(responseHandler: { [weak self] response in - guard let `self` = self else { return } - switch response { - case let .error(error): - reject("\(error)", "Encountered an error running the flow", error) - return; - case let .success(results): - resolve(createResponse(results, faceVariant: faceVariant)) - return; - case let .cancel(reason): - switch (reason) { - case .deniedConsent: - reject("deniedConsent", "User denied consent.", nil) - case .userExit: - reject("userExit", "User canceled flow.", nil) - default: - reject("userExit", "User canceled flow via unknown method.", nil) - } - return; - default: - reject("error", "Unknown error has occured", nil) - return; - } - }) + private func run(withConfig config: NSDictionary, + resolver resolve: @escaping RCTPromiseResolveBlock, + rejecter reject: @escaping RCTPromiseRejectBlock) { + + do { + // Copy the face varient from the config since it is not contained in the response: + let flowSteps:NSDictionary? = config["flowSteps"] as? NSDictionary + let captureFace:NSDictionary? = flowSteps?["captureFace"] as? NSDictionary + let faceVariant = captureFace?["type"] as? String + + let onfidoFlow: OnfidoFlow = try buildOnfidoFlow(from: config) + + onfidoFlow + .with(responseHandler: { response in + switch response { + case let .error(error): + reject("\(error)", "Encountered an error running the flow", error) + return; + case let .success(results): + resolve(createResponse(results, faceVariant: faceVariant)) + return; + case let .cancel(reason): + switch (reason) { + case .deniedConsent: + reject("deniedConsent", "User denied consent.", nil) + case .userExit: + reject("userExit", "User canceled flow.", nil) + default: + reject("userExit", "User canceled flow via unknown method.", nil) + } + return; + default: + reject("error", "Unknown error has occured", nil) + return; + } + }) let onfidoRun = try onfidoFlow.run() onfidoRun.modalPresentationStyle = .fullScreen @@ -248,16 +272,16 @@ extension UIColor { } private static func decideColor(light: UIColor, dark: UIColor) -> UIColor { - #if XCODE11 +#if XCODE11 guard #available(iOS 13.0, *) else { return light } return UIColor { (collection) -> UIColor in return collection.userInterfaceStyle == .dark ? dark : light } - #else +#else return light - #endif +#endif } static func from(hex: String) -> UIColor { diff --git a/ios/Podfile b/ios/Podfile index 3742f9d..fc100dd 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -4,7 +4,7 @@ platform :ios, '10.0' target 'OnfidoSdk' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! - pod 'Onfido', '24.6.0' + pod 'Onfido', '25.1.0' pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" diff --git a/ios/Response.swift b/ios/Response.swift index 1ed799a..f2151b0 100644 --- a/ios/Response.swift +++ b/ios/Response.swift @@ -10,28 +10,34 @@ import Foundation import Onfido func createResponse(_ results: [OnfidoResult], faceVariant: String?) -> [String: [String: Any]] { - var RNResponse = [String: [String: Any]]() - - let document: OnfidoResult? = results.filter({ result in - if case OnfidoResult.document = result { return true } - return false - }).first - - let face: OnfidoResult? = results.filter({ result in - if case OnfidoResult.face = result { return true } - return false - }).first - - if let documentUnwrapped = document, case OnfidoResult.document(let documentResponse) = documentUnwrapped { - RNResponse["document"] = ["front": ["id": documentResponse.front.id]] - if (documentResponse.back?.id != documentResponse.front.id) { - RNResponse["document"]?["back"] = ["id": documentResponse.back?.id] + var RNResponse = [String: [String: Any]]() + + let document: OnfidoResult? = results.filter({ result in + if case OnfidoResult.document = result { return true } + return false + }).first + + let face: OnfidoResult? = results.filter({ result in + if case OnfidoResult.face = result { return true } + return false + }).first + + if let documentUnwrapped = document, case OnfidoResult.document(let documentResponse) = documentUnwrapped { + RNResponse["document"] = ["front": ["id": documentResponse.front.id]] + if (documentResponse.back?.id != documentResponse.front.id) { + RNResponse["document"]?["back"] = ["id": documentResponse.back?.id] + } } - } - - if let faceUnwrapped = face, case OnfidoResult.face(let faceResponse) = faceUnwrapped { - RNResponse["face"] = ["id": faceResponse.id, "variant": faceVariant!] - } - - return RNResponse + + if let faceUnwrapped = face, case OnfidoResult.face(let faceResponse) = faceUnwrapped { + var faceResponse = ["id": faceResponse.id] + + if let faceVariant = faceVariant { + faceResponse["variant"] = faceVariant + } + + RNResponse["face"] = faceResponse + } + + return RNResponse } diff --git a/onfido-react-native-sdk.podspec b/onfido-react-native-sdk.podspec index 92f4ab2..3e6fc10 100644 --- a/onfido-react-native-sdk.podspec +++ b/onfido-react-native-sdk.podspec @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.requires_arc = true s.dependency "React" - s.dependency "Onfido", "24.6.0" + s.dependency "Onfido", "25.1.0" # ... # s.dependency "..." end diff --git a/package.json b/package.json index 0ae6d3d..c5b238e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@newagebel/react-native-onfido-sdk", "title": "React Native Onfido Sdk", - "version": "5.3.4", + "version": "5.4.4", "description": "Onfido React Native SDK", "main": "index.ts", "scripts": { diff --git a/src/Onfido.ts b/src/Onfido.ts index 50c5f72..6ede403 100644 --- a/src/Onfido.ts +++ b/src/Onfido.ts @@ -24,54 +24,59 @@ const Onfido = { return configError('sdkToken is not a valid jwt'); } - if (!config.flowSteps) { - return configError('flowSteps configuration is missing'); - } - - if (config.flowSteps.captureDocument) { - if ( - config.flowSteps.captureDocument.docType && - !config.flowSteps.captureDocument.countryCode - ) { - return configError( - 'countryCode needs to be a ISO 3166-1 3 letter code if docType is specified', - ); + if (config.workflowRunId === undefined) { + if (!config.flowSteps) { + return configError('flowSteps configuration is missing'); } - if ( - !config.flowSteps.captureDocument.docType && - config.flowSteps.captureDocument.countryCode - ) { - return configError('docType needs to be provided if countryCode is specified'); - } + if (config.flowSteps.captureDocument) { + if ( + config.flowSteps.captureDocument.docType && + !config.flowSteps.captureDocument.countryCode + ) { + return configError( + 'countryCode needs to be a ISO 3166-1 3 letter code if docType is specified', + ); + } - if ( - config.flowSteps.captureDocument.docType && - !(config.flowSteps.captureDocument.docType in OnfidoDocumentType) - ) { - return configError('docType is invalid'); - } + if ( + !config.flowSteps.captureDocument.docType && + config.flowSteps.captureDocument.countryCode + ) { + return configError('docType needs to be provided if countryCode is specified'); + } - if (config.flowSteps.captureDocument.countryCode) { - if (!(config.flowSteps.captureDocument.countryCode in OnfidoCountryCode)) { - return configError('countryCode is not a ISO 3166-1 3 letter code'); + if ( + config.flowSteps.captureDocument.docType && + !(config.flowSteps.captureDocument.docType in OnfidoDocumentType) + ) { + return configError('docType is invalid'); } - if (Platform.OS === 'android') { - config.flowSteps.captureDocument.alpha2CountryCode = - OnfidoAlpha2CountryCode[config.flowSteps.captureDocument.countryCode]; + if (config.flowSteps.captureDocument.countryCode) { + if (!(config.flowSteps.captureDocument.countryCode in OnfidoCountryCode)) { + return configError('countryCode is not a ISO 3166-1 3 letter code'); + } + + if (Platform.OS === 'android') { + config.flowSteps.captureDocument.alpha2CountryCode = + OnfidoAlpha2CountryCode[config.flowSteps.captureDocument.countryCode]; + } } } - } - if (!config.flowSteps.captureDocument && !config.flowSteps.captureFace) { - return configError( - "flowSteps doesn't include either valid captureDocument options or valid captureFace options", - ); - } + if (!config.flowSteps.captureDocument && !config.flowSteps.captureFace) { + return configError( + "flowSteps doesn't include either valid captureDocument options or valid captureFace options", + ); + } - if (config.flowSteps.captureFace && !(config.flowSteps.captureFace.type in OnfidoCaptureType)) { - return configError('Capture Face type is invalid'); + if ( + config.flowSteps.captureFace && + !(config.flowSteps.captureFace.type in OnfidoCaptureType) + ) { + return configError('Capture Face type is invalid'); + } } return OnfidoSdk.start(config).catch((error: any) => { diff --git a/src/types.ts b/src/types.ts index 2fd8983..3bd4cef 100644 --- a/src/types.ts +++ b/src/types.ts @@ -553,6 +553,7 @@ export type OnfidoResult = { export type OnfidoConfig = { sdkToken: string; flowSteps: OnfidoFlowSteps; + workflowRunId: string | null | undefined; }; export interface OnfidoError extends Error {