@smile_identity/react-native 10.2.4-beta.1 → 10.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +2 -1
- package/android/gradle.properties +1 -1
- package/android/src/main/java/com/smileidentity/react/Mapper.kt +1 -1
- package/android/src/main/java/com/smileidentity/react/viewmanagers/SmileIDBiometricKYCViewManager.kt +1 -0
- package/android/src/main/java/com/smileidentity/react/viewmanagers/SmileIDDocumentVerificationViewManager.kt +1 -0
- package/android/src/main/java/com/smileidentity/react/viewmanagers/SmileIDEnhancedDocumentVerificationViewManager.kt +1 -0
- package/android/src/main/java/com/smileidentity/react/views/SmileIDBiometricKYCView.kt +2 -0
- package/android/src/main/java/com/smileidentity/react/views/SmileIDDocumentVerificationView.kt +2 -0
- package/android/src/main/java/com/smileidentity/react/views/SmileIDEnhancedDocumentVerificationView.kt +2 -0
- package/ios/RNDelegates/SmileIDUIViewDelegate.swift +2 -0
- package/ios/RNSmileID.swift +482 -471
- package/ios/Utils/FileUtils.swift +17 -17
- package/ios/Utils/SmileIDDictExt.swift +29 -9
- package/ios/Utils/SmileIDUtils.swift +9 -0
- package/ios/View/BaseSmileIDView.swift +6 -5
- package/ios/View/SmileIDBiometricKYCView.swift +56 -54
- package/ios/View/SmileIDConsentView.swift +3 -2
- package/ios/View/SmileIDDocumentCaptureView.swift +64 -64
- package/ios/View/SmileIDDocumentVerificationView.swift +52 -51
- package/ios/View/SmileIDEnhancedDocumentVerificationView.swift +53 -50
- package/ios/View/SmileIDSmartSelfieAuthEnhancedView.swift +34 -33
- package/ios/View/SmileIDSmartSelfieAuthView.swift +35 -34
- package/ios/View/SmileIDSmartSelfieCaptureView.swift +55 -55
- package/ios/View/SmileIDSmartSelfieEnrollmentEnhancedView.swift +35 -34
- package/ios/View/SmileIDSmartSelfieEnrollmentView.swift +37 -36
- package/ios/ViewManagers/SmileIDBaseViewManager.swift +38 -25
- package/ios/ViewManagers/SmileIDBiometricKYCViewManager.swift +30 -24
- package/ios/ViewManagers/SmileIDConsentViewManager.swift +2 -2
- package/ios/ViewManagers/SmileIDDocumentCaptureViewManager.swift +19 -19
- package/ios/ViewManagers/SmileIDDocumentVerificationViewManager.swift +41 -40
- package/ios/ViewManagers/SmileIDEnhancedDocumentVerificationViewManager.swift +47 -40
- package/ios/ViewManagers/SmileIDSmartSelfieAuthenticationEnhancedViewManager.swift +16 -16
- package/ios/ViewManagers/SmileIDSmartSelfieAuthenticationViewManager.swift +20 -20
- package/ios/ViewManagers/SmileIDSmartSelfieCaptureViewManager.swift +27 -26
- package/ios/ViewManagers/SmileIDSmartSelfieEnrollmentEnhancedViewManager.swift +16 -16
- package/ios/ViewManagers/SmileIDSmartSelfieEnrollmentViewManager.swift +20 -20
- package/ios/ViewModels/SmileIDProductModel.swift +7 -5
- package/lib/commonjs/SmileIDBiometricKYCView.js +2 -11
- package/lib/commonjs/SmileIDBiometricKYCView.js.map +1 -1
- package/lib/commonjs/SmileIDEnhancedDocumentVerificationView.js +2 -11
- package/lib/commonjs/SmileIDEnhancedDocumentVerificationView.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types.js +31 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/useSmileIDView.js +16 -6
- package/lib/commonjs/useSmileIDView.js.map +1 -1
- package/lib/module/SmileIDBiometricKYCView.js +2 -11
- package/lib/module/SmileIDBiometricKYCView.js.map +1 -1
- package/lib/module/SmileIDEnhancedDocumentVerificationView.js +2 -11
- package/lib/module/SmileIDEnhancedDocumentVerificationView.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/types.js +29 -0
- package/lib/module/types.js.map +1 -1
- package/lib/module/useSmileIDView.js +17 -7
- package/lib/module/useSmileIDView.js.map +1 -1
- package/lib/typescript/SmileIDBiometricKYCView.d.ts.map +1 -1
- package/lib/typescript/SmileIDEnhancedDocumentVerificationView.d.ts +2 -2
- package/lib/typescript/SmileIDEnhancedDocumentVerificationView.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +17 -3
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/useSmileIDView.d.ts.map +1 -1
- package/package.json +1 -1
- package/react-native-smile-id.podspec +1 -1
- package/src/SmileIDBiometricKYCView.tsx +2 -9
- package/src/SmileIDEnhancedDocumentVerificationView.tsx +6 -16
- package/src/index.tsx +2 -0
- package/src/types.ts +62 -3
- package/src/useSmileIDView.tsx +17 -9
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
protocol SmileIDFileUtilsProtocol {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
var fileManager: FileManager { get set }
|
|
3
|
+
func getFilePath(fileName: String) -> String?
|
|
4
4
|
}
|
|
5
5
|
|
|
6
6
|
extension SmileIDFileUtilsProtocol {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
func getSmileIDDirectory() -> String? {
|
|
8
|
+
guard let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else {
|
|
9
|
+
print("Unable to access documents directory")
|
|
10
|
+
return nil
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let smileIDDirectory = documentsDirectory.appendingPathComponent("SmileID")
|
|
14
|
+
return smileIDDirectory.absoluteURL.absoluteString
|
|
11
15
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return nil
|
|
16
|
+
|
|
17
|
+
func getFilePath(fileName: String) -> String? {
|
|
18
|
+
guard let smileIDDirectory = getSmileIDDirectory() else {
|
|
19
|
+
return nil
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return (smileIDDirectory as NSString).appendingPathComponent(fileName)
|
|
20
23
|
}
|
|
21
|
-
|
|
22
|
-
return (smileIDDirectory as NSString).appendingPathComponent(fileName)
|
|
23
|
-
}
|
|
24
24
|
}
|
|
@@ -2,21 +2,21 @@ import Foundation
|
|
|
2
2
|
import SmileID
|
|
3
3
|
|
|
4
4
|
extension NSDictionary {
|
|
5
|
-
|
|
6
5
|
func toConfig() -> Config {
|
|
7
|
-
return Config
|
|
6
|
+
return Config(
|
|
8
7
|
partnerId: (self["partnerId"] as? String)!,
|
|
9
8
|
authToken: (self["authToken"] as? String)!,
|
|
10
9
|
prodLambdaUrl: (self["prodLambdaUrl"] as? String)!,
|
|
11
10
|
testLambdaUrl: (self["testLambdaUrl"] as? String)!
|
|
12
11
|
)
|
|
13
12
|
}
|
|
14
|
-
|
|
13
|
+
|
|
15
14
|
func toAuthenticationRequest() -> AuthenticationRequest? {
|
|
16
15
|
guard let jobTypeValue = self["jobType"] as? Int,
|
|
17
16
|
let jobType = JobType(rawValue: jobTypeValue),
|
|
18
17
|
let jobId = self["jobId"] as? String,
|
|
19
|
-
let userId = self["userId"] as? String
|
|
18
|
+
let userId = self["userId"] as? String
|
|
19
|
+
else {
|
|
20
20
|
return nil
|
|
21
21
|
}
|
|
22
22
|
|
|
@@ -40,7 +40,8 @@ extension NSDictionary {
|
|
|
40
40
|
let callbackUrl = self["callbackUrl"] as? String,
|
|
41
41
|
let partnerId = self["partnerId"] as? String,
|
|
42
42
|
let timestamp = self["timestamp"] as? String,
|
|
43
|
-
let signature = self["signature"] as? String
|
|
43
|
+
let signature = self["signature"] as? String
|
|
44
|
+
else {
|
|
44
45
|
return nil
|
|
45
46
|
}
|
|
46
47
|
|
|
@@ -70,7 +71,8 @@ extension NSDictionary {
|
|
|
70
71
|
func toUploadImageInfo() -> UploadImageInfo? {
|
|
71
72
|
guard let imageTypeIdValue = self["imageTypeId"] as? String,
|
|
72
73
|
let imageTypeId = ImageType(rawValue: imageTypeIdValue),
|
|
73
|
-
let imageName = self["imageName"] as? String
|
|
74
|
+
let imageName = self["imageName"] as? String
|
|
75
|
+
else {
|
|
74
76
|
return nil
|
|
75
77
|
}
|
|
76
78
|
|
|
@@ -107,6 +109,19 @@ extension NSDictionary {
|
|
|
107
109
|
)
|
|
108
110
|
}
|
|
109
111
|
|
|
112
|
+
func toConsentInfo() -> ConsentInformation {
|
|
113
|
+
let consentGrantedDate = self["consentGrantedDate"] as? String ?? getCurrentIsoTimestamp()
|
|
114
|
+
let personalDetailsConsentGranted = self["personalDetailsConsentGranted"] as? Bool ?? false
|
|
115
|
+
let contactInfoConsentGranted = self["contactInfoConsentGranted"] as? Bool ?? false
|
|
116
|
+
let documentInfoConsentGranted = self["documentInfoConsentGranted"] as? Bool ?? false
|
|
117
|
+
return ConsentInformation(
|
|
118
|
+
consentGrantedDate: consentGrantedDate,
|
|
119
|
+
personalDetailsConsentGranted: personalDetailsConsentGranted,
|
|
120
|
+
contactInformationConsentGranted: contactInfoConsentGranted,
|
|
121
|
+
documentInformationConsentGranted: documentInfoConsentGranted
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
110
125
|
func toEnhancedKycRequest() -> EnhancedKycRequest? {
|
|
111
126
|
guard let country = self["country"] as? String,
|
|
112
127
|
let idType = self["idType"] as? String,
|
|
@@ -119,9 +134,11 @@ extension NSDictionary {
|
|
|
119
134
|
let bankCode = self["bankCode"] as? String,
|
|
120
135
|
let callbackUrl = self["callbackUrl"] as? String,
|
|
121
136
|
let partnerParamsDict = self["partnerParams"] as? NSDictionary,
|
|
137
|
+
let consentInformation = self["consentInformation"] as? NSDictionary,
|
|
122
138
|
let partnerParams = partnerParamsDict.toPartnerParams(),
|
|
123
139
|
let timestamp = self["timestamp"] as? String,
|
|
124
|
-
let signature = self["signature"] as? String
|
|
140
|
+
let signature = self["signature"] as? String
|
|
141
|
+
else {
|
|
125
142
|
return nil
|
|
126
143
|
}
|
|
127
144
|
|
|
@@ -129,6 +146,7 @@ extension NSDictionary {
|
|
|
129
146
|
country: country,
|
|
130
147
|
idType: idType,
|
|
131
148
|
idNumber: idNumber,
|
|
149
|
+
consentInformation: consentInformation.toConsentInfo(),
|
|
132
150
|
firstName: firstName,
|
|
133
151
|
middleName: middleName,
|
|
134
152
|
lastName: lastName,
|
|
@@ -150,7 +168,8 @@ extension NSDictionary {
|
|
|
150
168
|
let includeHistory = self["includeHistory"] as? Bool,
|
|
151
169
|
let partnerId = self["partnerId"] as? String,
|
|
152
170
|
let timestamp = self["timestamp"] as? String,
|
|
153
|
-
let signature = self["signature"] as? String
|
|
171
|
+
let signature = self["signature"] as? String
|
|
172
|
+
else {
|
|
154
173
|
return nil
|
|
155
174
|
}
|
|
156
175
|
|
|
@@ -168,7 +187,8 @@ extension NSDictionary {
|
|
|
168
187
|
func toProductsConfigRequest() -> ProductsConfigRequest? {
|
|
169
188
|
guard let partnerId = self["partnerId"] as? String,
|
|
170
189
|
let timestamp = self["timestamp"] as? String,
|
|
171
|
-
let signature = self["signature"] as? String
|
|
190
|
+
let signature = self["signature"] as? String
|
|
191
|
+
else {
|
|
172
192
|
return nil
|
|
173
193
|
}
|
|
174
194
|
|
|
@@ -8,3 +8,12 @@ extension String {
|
|
|
8
8
|
return false
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
+
|
|
12
|
+
func getCurrentIsoTimestamp() -> String {
|
|
13
|
+
let pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
|
|
14
|
+
let formatter = DateFormatter()
|
|
15
|
+
formatter.dateFormat = pattern
|
|
16
|
+
formatter.locale = Locale(identifier: "en_US")
|
|
17
|
+
formatter.timeZone = TimeZone(identifier: "UTC")
|
|
18
|
+
return formatter.string(from: Date())
|
|
19
|
+
}
|
|
@@ -3,9 +3,9 @@ import SwiftUI
|
|
|
3
3
|
|
|
4
4
|
class BaseSmileIDView: UIView {
|
|
5
5
|
typealias ContentView = AnyView
|
|
6
|
-
var contentView
|
|
6
|
+
var contentView: AnyView?
|
|
7
7
|
private var _onResult: RCTBubblingEventBlock?
|
|
8
|
-
var product
|
|
8
|
+
var product: SmileIDProductModel?
|
|
9
9
|
|
|
10
10
|
@objc var onResult: RCTBubblingEventBlock? {
|
|
11
11
|
get {
|
|
@@ -19,7 +19,7 @@ class BaseSmileIDView: UIView {
|
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
init(frame: CGRect,contentView:AnyView,product:SmileIDProductModel) {
|
|
22
|
+
init(frame: CGRect, contentView: AnyView, product: SmileIDProductModel) {
|
|
23
23
|
self.contentView = contentView
|
|
24
24
|
self.product = product
|
|
25
25
|
super.init(frame: frame)
|
|
@@ -34,7 +34,7 @@ class BaseSmileIDView: UIView {
|
|
|
34
34
|
private func commonInit() {
|
|
35
35
|
// Perform initialization tasks here
|
|
36
36
|
// For example, setup subviews, add constraints, configure appearance
|
|
37
|
-
let hostingController = UIHostingController(rootView:contentView)
|
|
37
|
+
let hostingController = UIHostingController(rootView: contentView)
|
|
38
38
|
let hostingView = hostingController.view!
|
|
39
39
|
hostingView.translatesAutoresizingMaskIntoConstraints = false
|
|
40
40
|
addSubview(hostingView)
|
|
@@ -42,9 +42,10 @@ class BaseSmileIDView: UIView {
|
|
|
42
42
|
hostingView.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
|
|
43
43
|
hostingView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
|
|
44
44
|
hostingView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
|
|
45
|
+
hostingView.overrideUserInterfaceStyle = .light
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
func getView(product:SmileIDProductModel) -> AnyView {
|
|
48
|
+
func getView(product _: SmileIDProductModel) -> AnyView {
|
|
48
49
|
fatalError("Must be implemented by subclass")
|
|
49
50
|
}
|
|
50
51
|
}
|
|
@@ -2,62 +2,64 @@ import Foundation
|
|
|
2
2
|
import SmileID
|
|
3
3
|
import SwiftUI
|
|
4
4
|
|
|
5
|
-
struct SmileIDBiometricKYCView: View
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
5
|
+
struct SmileIDBiometricKYCView: View, SmileIDFileUtilsProtocol {
|
|
6
|
+
var fileManager: FileManager = Foundation.FileManager.default
|
|
7
|
+
@ObservedObject var product: SmileIDProductModel
|
|
8
|
+
var smileIDUIViewDelegate: SmileIDUIViewDelegate
|
|
9
|
+
var body: some View {
|
|
10
|
+
NavigationView {
|
|
11
|
+
if let idInfo = product.idInfo, let consentInformation = product.consentInformation {
|
|
12
|
+
SmileID.biometricKycScreen(
|
|
13
|
+
idInfo: idInfo,
|
|
14
|
+
consentInformation: consentInformation, // already validated in the SmileIDBiometricKYCViewManager
|
|
15
|
+
userId: product.userId ?? generateUserId(),
|
|
16
|
+
jobId: product.jobId ?? generateJobId(),
|
|
17
|
+
allowNewEnroll: product.allowNewEnroll,
|
|
18
|
+
allowAgentMode: product.allowAgentMode,
|
|
19
|
+
showAttribution: product.showAttribution,
|
|
20
|
+
showInstructions: product.showInstructions,
|
|
21
|
+
useStrictMode: product.useStrictMode,
|
|
22
|
+
extraPartnerParams: product.extraPartnerParams as [String: String],
|
|
23
|
+
delegate: self
|
|
24
|
+
)
|
|
25
|
+
} else {
|
|
26
|
+
// This exists for debugging purposes and will show in extreme cases
|
|
27
|
+
// when the params were not set NB: setParams in the viewmanager will always
|
|
28
|
+
// return an error if the required data is missing
|
|
29
|
+
Text("An error has occured")
|
|
30
|
+
}
|
|
31
|
+
}.navigationViewStyle(StackNavigationViewStyle())
|
|
32
|
+
}
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
extension SmileIDBiometricKYCView: BiometricKycResultDelegate {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
func didSucceed(selfieImage: URL, livenessImages: [URL], didSubmitBiometricJob: Bool) {
|
|
37
|
+
let params: [String: Any] = [
|
|
38
|
+
"selfieFile": getFilePath(fileName: selfieImage.absoluteString),
|
|
39
|
+
"livenessFiles": livenessImages.map {
|
|
40
|
+
getFilePath(fileName: $0.absoluteString)
|
|
41
|
+
},
|
|
42
|
+
"didSubmitBiometricKycJob": didSubmitBiometricJob,
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
guard let jsonData = try? JSONSerialization.data(withJSONObject: params.toJSONCompatibleDictionary(), options: .prettyPrinted) else {
|
|
46
|
+
smileIDUIViewDelegate.onError(error: SmileIDError.unknown("SmileIDBiometricKYCView encoding error"))
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
smileIDUIViewDelegate.onResult(smileResult: String(data: jsonData, encoding: .utf8)!)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
func didSucceed(
|
|
53
|
+
selfieImage _: URL,
|
|
54
|
+
livenessImages _: [URL],
|
|
55
|
+
jobStatusResponse: BiometricKycJobStatusResponse
|
|
56
|
+
) {
|
|
57
|
+
let encoder = JSONEncoder()
|
|
58
|
+
let jsonData = try! encoder.encode(jobStatusResponse)
|
|
59
|
+
smileIDUIViewDelegate.onResult(smileResult: String(data: jsonData, encoding: .utf8)!)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
func didError(error: Error) {
|
|
63
|
+
smileIDUIViewDelegate.onError(error: error)
|
|
46
64
|
}
|
|
47
|
-
product.onResult?(["result": String(data: jsonData, encoding: .utf8)!])
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
func didSucceed(
|
|
51
|
-
selfieImage _: URL,
|
|
52
|
-
livenessImages _: [URL],
|
|
53
|
-
jobStatusResponse: BiometricKycJobStatusResponse
|
|
54
|
-
) {
|
|
55
|
-
let encoder = JSONEncoder()
|
|
56
|
-
let jsonData = try! encoder.encode(jobStatusResponse)
|
|
57
|
-
product.onResult?(["result": String(data: jsonData, encoding: .utf8)!])
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
func didError(error: Error) {
|
|
61
|
-
product.onResult?(["error": error.localizedDescription])
|
|
62
|
-
}
|
|
63
65
|
}
|
|
@@ -3,8 +3,9 @@ import SmileID
|
|
|
3
3
|
import SwiftUI
|
|
4
4
|
|
|
5
5
|
struct SmileIDConsentView: View {
|
|
6
|
-
@ObservedObject var product
|
|
6
|
+
@ObservedObject var product: SmileIDProductModel
|
|
7
7
|
var onResult: RCTBubblingEventBlock?
|
|
8
|
+
var smileIDUIViewDelegate: SmileIDUIViewDelegate
|
|
8
9
|
var body: some View {
|
|
9
10
|
NavigationView {
|
|
10
11
|
if let partnerIcon = product.partnerIcon,
|
|
@@ -19,7 +20,7 @@ struct SmileIDConsentView: View {
|
|
|
19
20
|
productName: productName,
|
|
20
21
|
partnerPrivacyPolicy: URL(string: partnerPrivacyPolicy)!,
|
|
21
22
|
showAttribution: true,
|
|
22
|
-
onConsentGranted: {
|
|
23
|
+
onConsentGranted: { _ in
|
|
23
24
|
DispatchQueue.main.async {
|
|
24
25
|
self.product.onResult?(["result": true])
|
|
25
26
|
}
|
|
@@ -3,80 +3,80 @@ import SmileID
|
|
|
3
3
|
import SwiftUI
|
|
4
4
|
|
|
5
5
|
struct DocumentCaptureResult {
|
|
6
|
-
|
|
6
|
+
let documentFile: URL? // Using URL to represent file paths in Swift
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
init(documentFile: URL?) {
|
|
9
|
+
self.documentFile = documentFile
|
|
10
|
+
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
struct SmileIDDocumentCaptureView: View {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
func onConfirmed(data: Data) {
|
|
42
|
-
do {
|
|
43
|
-
// Attempt to create the document file
|
|
44
|
-
let url = try LocalStorage.createDocumentFile(
|
|
45
|
-
jobId: self.product.jobId ?? generateJobId(),
|
|
46
|
-
fileType: self.product.front ? FileType.documentFront : FileType.documentBack,
|
|
47
|
-
document: data
|
|
48
|
-
)
|
|
14
|
+
@ObservedObject var product: SmileIDProductModel
|
|
15
|
+
@State private var localMetadata = LocalMetadata()
|
|
16
|
+
var smileIDUIViewDelegate: SmileIDUIViewDelegate
|
|
17
|
+
var body: some View {
|
|
18
|
+
NavigationView {
|
|
19
|
+
DocumentCaptureScreen(
|
|
20
|
+
side: self.product.front ? .front : .back,
|
|
21
|
+
showInstructions: self.product.showInstructions,
|
|
22
|
+
showAttribution: self.product.showAttribution,
|
|
23
|
+
allowGallerySelection: self.product.allowGalleryUpload,
|
|
24
|
+
showSkipButton: false,
|
|
25
|
+
instructionsHeroImage: self.product.front ? SmileIDResourcesHelper.DocVFrontHero : SmileIDResourcesHelper.DocVBackHero,
|
|
26
|
+
instructionsTitleText: SmileIDResourcesHelper.localizedString(
|
|
27
|
+
for: self.product.front ? "Instructions.Document.Front.Header" : "Instructions.Document.Back.Header"
|
|
28
|
+
),
|
|
29
|
+
instructionsSubtitleText: SmileIDResourcesHelper.localizedString(
|
|
30
|
+
for: self.product.front ? "Instructions.Document.Front.Callout" : "Instructions.Document.Back.Callout"
|
|
31
|
+
),
|
|
32
|
+
captureTitleText: SmileIDResourcesHelper.localizedString(for: "Action.TakePhoto"),
|
|
33
|
+
knownIdAspectRatio: self.product.idAspectRatio,
|
|
34
|
+
showConfirmation: self.product.showConfirmation,
|
|
35
|
+
onConfirm: onConfirmed,
|
|
36
|
+
onError: onError,
|
|
37
|
+
onSkip: onSkip
|
|
38
|
+
)
|
|
39
|
+
}.navigationViewStyle(StackNavigationViewStyle()).environmentObject(localMetadata)
|
|
40
|
+
}
|
|
49
41
|
|
|
42
|
+
func onConfirmed(data: Data) {
|
|
43
|
+
do {
|
|
44
|
+
// Attempt to create the document file
|
|
45
|
+
let url = try LocalStorage.createDocumentFile(
|
|
46
|
+
jobId: product.jobId ?? generateJobId(),
|
|
47
|
+
fileType: product.front ? FileType.documentFront : FileType.documentBack,
|
|
48
|
+
document: data
|
|
49
|
+
)
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
// Create params dictionary
|
|
52
|
+
var params: [String: Any] = [
|
|
53
|
+
"documentFrontImage": product.front ? url.absoluteString : nil,
|
|
54
|
+
"documentBackImage": product.front ? nil : url.absoluteString,
|
|
55
|
+
]
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
57
|
+
// Convert params to JSON-compatible dictionary and serialize to JSON
|
|
58
|
+
guard let jsonData = try? JSONSerialization.data(withJSONObject: params.toJSONCompatibleDictionary(), options: .prettyPrinted),
|
|
59
|
+
let jsonString = String(data: jsonData, encoding: .utf8)
|
|
60
|
+
else {
|
|
61
|
+
// If serialization fails, call the error handler
|
|
62
|
+
smileIDUIViewDelegate.onError(error: SmileIDError.unknown("SmileIDDocumentCaptureView encoding error"))
|
|
63
|
+
return
|
|
64
|
+
}
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
66
|
+
// Send the result as a JSON string
|
|
67
|
+
smileIDUIViewDelegate.onResult(smileResult: jsonString)
|
|
67
68
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
} catch {
|
|
70
|
+
// Handle file creation error
|
|
71
|
+
smileIDUIViewDelegate.onError(error: SmileIDError.unknown("Error creating document file: \(error.localizedDescription)"))
|
|
72
|
+
}
|
|
71
73
|
}
|
|
72
|
-
}
|
|
73
74
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
func onError(error: Error) {
|
|
76
|
+
smileIDUIViewDelegate.onError(error: error)
|
|
77
|
+
}
|
|
77
78
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
func onSkip() {
|
|
80
|
+
smileIDUIViewDelegate.onError(error: SmileIDError.unknown("SmileIDDocumentCaptureView skipped"))
|
|
81
|
+
}
|
|
81
82
|
}
|
|
82
|
-
|
|
@@ -2,60 +2,61 @@ import Foundation
|
|
|
2
2
|
import SmileID
|
|
3
3
|
import SwiftUI
|
|
4
4
|
|
|
5
|
-
struct SmileIDDocumentVerificationView: View
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
5
|
+
struct SmileIDDocumentVerificationView: View, SmileIDFileUtilsProtocol {
|
|
6
|
+
var fileManager: FileManager = Foundation.FileManager.default
|
|
7
|
+
@ObservedObject var product: SmileIDProductModel
|
|
8
|
+
var smileIDUIViewDelegate: SmileIDUIViewDelegate
|
|
9
|
+
var body: some View {
|
|
10
|
+
AnyView(NavigationView {
|
|
11
|
+
if let countryCode = product.countryCode {
|
|
12
|
+
SmileID.documentVerificationScreen(
|
|
13
|
+
userId: product.userId ?? generateUserId(),
|
|
14
|
+
jobId: product.jobId ?? generateJobId(),
|
|
15
|
+
allowNewEnroll: product.allowNewEnroll,
|
|
16
|
+
countryCode: countryCode, // already validated in SmileIDDocumentVerificationViewManager
|
|
17
|
+
documentType: product.documentType,
|
|
18
|
+
idAspectRatio: product.idAspectRatio,
|
|
19
|
+
bypassSelfieCaptureWithFile: product.bypassSelfieCaptureWithFilePath,
|
|
20
|
+
captureBothSides: product.captureBothSides,
|
|
21
|
+
allowAgentMode: product.allowAgentMode,
|
|
22
|
+
allowGalleryUpload: product.allowGalleryUpload,
|
|
23
|
+
showInstructions: product.showInstructions,
|
|
24
|
+
showAttribution: product.showAttribution,
|
|
25
|
+
skipApiSubmission: product.skipApiSubmission,
|
|
26
|
+
useStrictMode: product.useStrictMode,
|
|
27
|
+
extraPartnerParams: product.extraPartnerParams as [String: String],
|
|
28
|
+
delegate: self
|
|
29
|
+
)
|
|
30
|
+
} else {
|
|
31
|
+
// This exists for debugging purposes and will show in extreme cases
|
|
32
|
+
// when the params were not set NB: setParams in the viewmanager will always
|
|
33
|
+
// return an error if the required data is missing
|
|
34
|
+
Text("An error has occured")
|
|
35
|
+
}
|
|
36
|
+
}.navigationViewStyle(StackNavigationViewStyle()))
|
|
37
|
+
}
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
extension SmileIDDocumentVerificationView: DocumentVerificationResultDelegate {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
func didSucceed(selfie: URL, documentFrontImage: URL, documentBackImage: URL?, didSubmitDocumentVerificationJob: Bool) {
|
|
42
|
+
var params: [String: Any] = [
|
|
43
|
+
"selfieFile": getFilePath(fileName: selfie.absoluteString),
|
|
44
|
+
"documentFrontFile": getFilePath(fileName: documentFrontImage.absoluteString),
|
|
45
|
+
"didSubmitDocumentVerificationJob": didSubmitDocumentVerificationJob,
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
if let documentBackImage = documentBackImage {
|
|
49
|
+
params["documentBackFile"] = getFilePath(fileName: documentBackImage.absoluteString)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
guard let jsonData = try? JSONSerialization.data(withJSONObject: params.toJSONCompatibleDictionary(), options: .prettyPrinted) else {
|
|
53
|
+
smileIDUIViewDelegate.onError(error: SmileIDError.unknown("SmileIDDocumentVerificationView encoding error"))
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
smileIDUIViewDelegate.onResult(smileResult: String(data: jsonData, encoding: .utf8)!)
|
|
49
57
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return
|
|
58
|
+
|
|
59
|
+
func didError(error: Error) {
|
|
60
|
+
smileIDUIViewDelegate.onError(error: error)
|
|
54
61
|
}
|
|
55
|
-
product.onResult?(["result": String(data: jsonData, encoding: .utf8)!])
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
func didError(error: Error) {
|
|
59
|
-
product.onResult?(["error": error.localizedDescription])
|
|
60
|
-
}
|
|
61
62
|
}
|