@smile_identity/react-native 10.0.0-beta03 → 10.0.0

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.
Files changed (39) hide show
  1. package/android/src/main/java/com/smileidentity/react/Mapper.kt +2 -9
  2. package/android/src/main/java/com/smileidentity/react/viewmanagers/SmileIDDocumentVerificationViewManager.kt +1 -1
  3. package/android/src/main/java/com/smileidentity/react/viewmanagers/SmileIDEnhancedDocumentVerificationViewManager.kt +1 -1
  4. package/android/src/main/java/com/smileidentity/react/views/CustomViewModelStoreOwner.kt +12 -0
  5. package/android/src/main/java/com/smileidentity/react/views/SmileIDBiometricKYCView.kt +2 -4
  6. package/android/src/main/java/com/smileidentity/react/views/SmileIDConsentView.kt +2 -4
  7. package/android/src/main/java/com/smileidentity/react/views/SmileIDDocumentVerificationView.kt +3 -4
  8. package/android/src/main/java/com/smileidentity/react/views/SmileIDEnhancedDocumentVerificationView.kt +4 -4
  9. package/android/src/main/java/com/smileidentity/react/views/SmileIDSmartSelfieAuthenticationView.kt +2 -4
  10. package/android/src/main/java/com/smileidentity/react/views/SmileIDSmartSelfieEnrollmentView.kt +2 -4
  11. package/android/src/main/java/com/smileidentity/react/views/SmileIDView.kt +19 -7
  12. package/ios/RNSmileID.mm +10 -0
  13. package/ios/RNSmileID.swift +137 -0
  14. package/ios/Utils/SmileIDDictExt.swift +145 -6
  15. package/ios/View/BaseSmileIDView.swift +22 -5
  16. package/ios/View/SmileIDConsentView.swift +10 -4
  17. package/ios/ViewManagers/SmileIDBaseViewManager.swift +13 -4
  18. package/ios/ViewManagers/SmileIDBiometricKYCViewManager.m +1 -0
  19. package/ios/ViewManagers/SmileIDBiometricKYCViewManager.swift +1 -1
  20. package/ios/ViewManagers/SmileIDConsentViewManager.m +1 -0
  21. package/ios/ViewManagers/SmileIDConsentViewManager.swift +3 -3
  22. package/ios/ViewManagers/SmileIDDocumentVerificationViewManager.m +1 -0
  23. package/ios/ViewManagers/SmileIDDocumentVerificationViewManager.swift +1 -1
  24. package/ios/ViewManagers/SmileIDEnhancedDocumentVerificationViewManager.m +1 -0
  25. package/ios/ViewManagers/SmileIDEnhancedDocumentVerificationViewManager.swift +1 -1
  26. package/ios/ViewManagers/SmileIDSmartSelfieAuthenticationViewManager.m +1 -0
  27. package/ios/ViewManagers/SmileIDSmartSelfieAuthenticationViewManager.swift +1 -1
  28. package/ios/ViewManagers/SmileIDSmartSelfieEnrollmentViewManager.m +1 -0
  29. package/ios/ViewManagers/SmileIDSmartSelfieEnrollmentViewManager.swift +2 -2
  30. package/ios/ViewModels/SmileIDProductModel.swift +1 -1
  31. package/lib/commonjs/index.js +48 -4
  32. package/lib/commonjs/index.js.map +1 -1
  33. package/lib/module/index.js +43 -5
  34. package/lib/module/index.js.map +1 -1
  35. package/lib/typescript/index.d.ts +43 -5
  36. package/lib/typescript/index.d.ts.map +1 -1
  37. package/package.json +1 -1
  38. package/react-native-smile-id.podspec +1 -1
  39. package/src/index.tsx +64 -6
@@ -46,13 +46,6 @@ fun ReadableMap.toPartnerParams(): PartnerParams {
46
46
  )
47
47
  }
48
48
 
49
- fun ReadableMap.toConsentInfo(): ConsentInfo {
50
- return ConsentInfo(
51
- canAccess = getBoolOrDefault("canAccess", false),
52
- consentRequired = getBoolOrDefault("consentRequired", true)
53
- )
54
- }
55
-
56
49
  fun ReadableMap.toPrepUploadRequest(): PrepUploadRequest {
57
50
  return PrepUploadRequest(
58
51
  partnerParams = getMapOrDefault("partnerParams")?.toPartnerParams() ?: run {
@@ -62,7 +55,7 @@ fun ReadableMap.toPrepUploadRequest(): PrepUploadRequest {
62
55
  partnerId = getStringOrDefault("partnerId") ?: run {
63
56
  throw IllegalArgumentException("partnerId is required")
64
57
  },
65
- sourceSdk = getStringOrDefault("sourceSdk") ?: "react-native",
58
+ sourceSdk = getStringOrDefault("sourceSdk") ?: "android (react-native)",
66
59
  timestamp = getStringOrDefault("timestamp") ?: run {
67
60
  throw IllegalArgumentException("timestamp is required")
68
61
  },
@@ -132,7 +125,7 @@ fun ReadableMap.toEnhancedKycRequest(): EnhancedKycRequest {
132
125
  partnerParams = getMapOrDefault("partnerParams")?.toPartnerParams() ?: run {
133
126
  throw IllegalArgumentException("partnerParams is required")
134
127
  },
135
- sourceSdk = getStringOrDefault("sourceSdk") ?: "react-native",
128
+ sourceSdk = getStringOrDefault("sourceSdk") ?: "android (react-native)",
136
129
  timestamp = getStringOrDefault("timestamp") ?: run {
137
130
  throw IllegalArgumentException("timestamp is required")
138
131
  },
@@ -58,7 +58,7 @@ class SmileIDDocumentVerificationViewManager(private val reactApplicationContext
58
58
  view.allowGalleryUpload = params.getBoolOrDefault("allowGalleryUpload", false)
59
59
  view.bypassSelfieCaptureWithFilePath = params.getStringOrDefault("bypassSelfieCaptureWithFilePath", null)
60
60
  view.documentType = params.getStringOrDefault("documentType", null)
61
- view.idAspectRatio = params.getFloatOrDefault("idAspectRatio", -1f)
61
+ view.idAspectRatio = params.getFloatOrDefault("idAspectRatio")
62
62
  view.allowNewEnroll = params.getBoolOrDefault("allowNewEnroll", false)
63
63
  view.renderContent()
64
64
  }
@@ -57,7 +57,7 @@ class SmileIDEnhancedDocumentVerificationViewManager(private val reactApplicatio
57
57
  view.showInstructions = params.getBoolOrDefault("showInstructions", true)
58
58
  view.allowGalleryUpload = params.getBoolOrDefault("allowGalleryUpload", false)
59
59
  view.documentType = params.getStringOrDefault("documentType")
60
- view.idAspectRatio = params.getFloatOrDefault("idAspectRatio", -1f)
60
+ view.idAspectRatio = params.getFloatOrDefault("idAspectRatio")
61
61
  view.allowNewEnroll = params.getBoolOrDefault("allowNewEnroll", false)
62
62
  view.renderContent()
63
63
  }
@@ -0,0 +1,12 @@
1
+ package com.smileidentity.react.views
2
+
3
+ import androidx.lifecycle.ViewModelStore
4
+ import androidx.lifecycle.ViewModelStoreOwner
5
+
6
+ class CustomViewModelStoreOwner : ViewModelStoreOwner {
7
+ override val viewModelStore: ViewModelStore = ViewModelStore()
8
+
9
+ fun clear() {
10
+ viewModelStore.clear()
11
+ }
12
+ }
@@ -2,8 +2,6 @@ package com.smileidentity.react.views
2
2
 
3
3
  import androidx.compose.runtime.CompositionLocalProvider
4
4
  import androidx.compose.runtime.saveable.rememberSaveable
5
- import androidx.compose.ui.platform.ViewCompositionStrategy
6
- import androidx.lifecycle.ViewModelStoreOwner
7
5
  import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
8
6
  import com.facebook.react.bridge.ReactApplicationContext
9
7
  import com.smileidentity.SmileID
@@ -24,9 +22,9 @@ class SmileIDBiometricKYCView(context: ReactApplicationContext) : SmileIDView(co
24
22
  return
25
23
  }
26
24
  composeView.apply {
27
- setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindow)
25
+ val customViewModelStoreOwner = CustomViewModelStoreOwner()
28
26
  setContent {
29
- CompositionLocalProvider(LocalViewModelStoreOwner provides (context as ViewModelStoreOwner)) {
27
+ CompositionLocalProvider(LocalViewModelStoreOwner provides customViewModelStoreOwner) {
30
28
  SmileID.BiometricKYC(
31
29
  idInfo = idInfo!!,
32
30
  userId = userId ?: rememberSaveable { randomUserId() },
@@ -2,9 +2,7 @@ package com.smileidentity.react.views
2
2
 
3
3
  import android.webkit.URLUtil
4
4
  import androidx.compose.runtime.CompositionLocalProvider
5
- import androidx.compose.ui.platform.ViewCompositionStrategy
6
5
  import androidx.compose.ui.res.painterResource
7
- import androidx.lifecycle.ViewModelStoreOwner
8
6
  import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
9
7
  import com.facebook.react.bridge.ReactApplicationContext
10
8
  import com.smileidentity.SmileID
@@ -43,9 +41,9 @@ class SmileIDConsentView(context: ReactApplicationContext) : SmileIDView(context
43
41
  (context as? ReactApplicationContext)?.currentActivity?.packageName
44
42
  )
45
43
  composeView.apply {
46
- setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindow)
44
+ val customViewModelStoreOwner = CustomViewModelStoreOwner()
47
45
  setContent {
48
- CompositionLocalProvider(LocalViewModelStoreOwner provides (context as ViewModelStoreOwner)) {
46
+ CompositionLocalProvider(LocalViewModelStoreOwner provides customViewModelStoreOwner) {
49
47
  SmileID.ConsentScreen(
50
48
  partnerIcon = painterResource(
51
49
  id = partnerIcon
@@ -2,8 +2,6 @@ package com.smileidentity.react.views
2
2
 
3
3
  import androidx.compose.runtime.CompositionLocalProvider
4
4
  import androidx.compose.runtime.saveable.rememberSaveable
5
- import androidx.compose.ui.platform.ViewCompositionStrategy
6
- import androidx.lifecycle.ViewModelStoreOwner
7
5
  import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
8
6
  import com.facebook.react.bridge.ReactApplicationContext
9
7
  import com.smileidentity.SmileID
@@ -34,9 +32,9 @@ class SmileIDDocumentVerificationView(context: ReactApplicationContext) : SmileI
34
32
  bypassSelfieCaptureWithFile = File(it)
35
33
  }
36
34
  composeView.apply {
37
- setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindow)
35
+ val customViewModelStoreOwner = CustomViewModelStoreOwner()
38
36
  setContent {
39
- CompositionLocalProvider(LocalViewModelStoreOwner provides (context as ViewModelStoreOwner)) {
37
+ CompositionLocalProvider(LocalViewModelStoreOwner provides customViewModelStoreOwner) {
40
38
  SmileID.DocumentVerification(
41
39
  userId = userId ?: rememberSaveable { randomUserId() },
42
40
  jobId = jobId ?: rememberSaveable { randomJobId() },
@@ -44,6 +42,7 @@ class SmileIDDocumentVerificationView(context: ReactApplicationContext) : SmileI
44
42
  documentType = documentType,
45
43
  idAspectRatio = idAspectRatio,
46
44
  showAttribution = showAttribution ?: true,
45
+ allowAgentMode = allowAgentMode ?: false,
47
46
  showInstructions = showInstructions ?: true,
48
47
  allowGalleryUpload = allowGalleryUpload,
49
48
  captureBothSides = captureBothSides,
@@ -2,8 +2,6 @@ package com.smileidentity.react.views
2
2
 
3
3
  import androidx.compose.runtime.CompositionLocalProvider
4
4
  import androidx.compose.runtime.saveable.rememberSaveable
5
- import androidx.compose.ui.platform.ViewCompositionStrategy
6
- import androidx.lifecycle.ViewModelStoreOwner
7
5
  import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
8
6
  import com.facebook.react.bridge.ReactApplicationContext
9
7
  import com.smileidentity.SmileID
@@ -28,10 +26,11 @@ class SmileIDEnhancedDocumentVerificationView(context: ReactApplicationContext)
28
26
  emitFailure(IllegalArgumentException("countryCode is required for DocumentVerification"))
29
27
  return;
30
28
  }
29
+
31
30
  composeView.apply {
32
- setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindow)
31
+ val customViewModelStoreOwner = CustomViewModelStoreOwner()
33
32
  setContent {
34
- CompositionLocalProvider(LocalViewModelStoreOwner provides (context as ViewModelStoreOwner)) {
33
+ CompositionLocalProvider(LocalViewModelStoreOwner provides customViewModelStoreOwner) {
35
34
  SmileID.EnhancedDocumentVerificationScreen(
36
35
  userId = userId ?: rememberSaveable { randomUserId() },
37
36
  jobId = jobId ?: rememberSaveable { randomJobId() },
@@ -39,6 +38,7 @@ class SmileIDEnhancedDocumentVerificationView(context: ReactApplicationContext)
39
38
  documentType = documentType,
40
39
  idAspectRatio = idAspectRatio,
41
40
  showAttribution = showAttribution ?: true,
41
+ allowAgentMode = allowAgentMode ?: false,
42
42
  showInstructions = showInstructions ?: true,
43
43
  allowNewEnroll = allowNewEnroll ?: false,
44
44
  allowGalleryUpload = allowGalleryUpload,
@@ -2,8 +2,6 @@ package com.smileidentity.react.views
2
2
 
3
3
  import androidx.compose.runtime.CompositionLocalProvider
4
4
  import androidx.compose.runtime.saveable.rememberSaveable
5
- import androidx.compose.ui.platform.ViewCompositionStrategy
6
- import androidx.lifecycle.ViewModelStoreOwner
7
5
  import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
8
6
  import com.facebook.react.bridge.ReactApplicationContext
9
7
  import com.smileidentity.SmileID
@@ -20,9 +18,9 @@ class SmileIDSmartSelfieAuthenticationView(context: ReactApplicationContext) :
20
18
 
21
19
  override fun renderContent() {
22
20
  composeView.apply {
23
- setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindow)
21
+ val customViewModelStoreOwner = CustomViewModelStoreOwner()
24
22
  setContent {
25
- CompositionLocalProvider(LocalViewModelStoreOwner provides (context as ViewModelStoreOwner)) {
23
+ CompositionLocalProvider(LocalViewModelStoreOwner provides customViewModelStoreOwner) {
26
24
  SmileID.SmartSelfieAuthentication(
27
25
  userId = userId ?: rememberSaveable { randomUserId() },
28
26
  jobId = jobId ?: rememberSaveable { randomJobId() },
@@ -2,8 +2,6 @@ package com.smileidentity.react.views
2
2
 
3
3
  import androidx.compose.runtime.CompositionLocalProvider
4
4
  import androidx.compose.runtime.saveable.rememberSaveable
5
- import androidx.compose.ui.platform.ViewCompositionStrategy
6
- import androidx.lifecycle.ViewModelStoreOwner
7
5
  import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
8
6
  import com.facebook.react.bridge.ReactApplicationContext
9
7
  import com.smileidentity.SmileID
@@ -19,9 +17,9 @@ class SmileIDSmartSelfieEnrollmentView(context: ReactApplicationContext) : Smile
19
17
 
20
18
  override fun renderContent() {
21
19
  composeView.apply {
22
- setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindow)
20
+ val customViewModelStoreOwner = CustomViewModelStoreOwner()
23
21
  setContent {
24
- CompositionLocalProvider(LocalViewModelStoreOwner provides (context as ViewModelStoreOwner)) {
22
+ CompositionLocalProvider(LocalViewModelStoreOwner provides customViewModelStoreOwner) {
25
23
  SmileID.SmartSelfieEnrollment(
26
24
  userId = userId ?: rememberSaveable { randomUserId() },
27
25
  jobId = jobId ?: rememberSaveable { randomJobId() },
@@ -4,6 +4,7 @@ import android.view.Choreographer
4
4
  import android.view.ViewGroup
5
5
  import android.widget.LinearLayout
6
6
  import androidx.compose.ui.platform.ComposeView
7
+ import androidx.core.view.contains
7
8
  import com.facebook.react.bridge.Arguments
8
9
  import com.facebook.react.bridge.ReactApplicationContext
9
10
  import com.facebook.react.bridge.ReactContext
@@ -13,7 +14,7 @@ import com.smileidentity.models.JobType
13
14
  import timber.log.Timber
14
15
 
15
16
  abstract class SmileIDView(context: ReactApplicationContext) : LinearLayout(context) {
16
- val composeView: ComposeView = ComposeView(context.currentActivity!!)
17
+ lateinit var composeView: ComposeView
17
18
  var userId: String? = null
18
19
  var jobId: String? = null
19
20
  private var jobType: JobType? = null
@@ -35,19 +36,30 @@ abstract class SmileIDView(context: ReactApplicationContext) : LinearLayout(cont
35
36
  orientation = VERTICAL
36
37
  render()
37
38
 
38
- composeView.layoutParams = ViewGroup.LayoutParams(
39
- ViewGroup.LayoutParams.MATCH_PARENT,
40
- ViewGroup.LayoutParams.MATCH_PARENT
41
- )
42
- addView(composeView)
43
-
44
39
  setupLayoutHack()
45
40
  manuallyLayoutChildren()
46
41
  }
47
42
 
43
+ private fun setUpViews() {
44
+ if (::composeView.isInitialized && contains(composeView)) {
45
+ removeView(composeView)
46
+ }
47
+ (context as ReactContext).currentActivity?.let {
48
+ it.runOnUiThread {
49
+ composeView = ComposeView(it)
50
+ composeView.layoutParams = ViewGroup.LayoutParams(
51
+ ViewGroup.LayoutParams.MATCH_PARENT,
52
+ ViewGroup.LayoutParams.MATCH_PARENT
53
+ )
54
+ addView(composeView)
55
+ }
56
+ }
57
+ }
58
+
48
59
  abstract fun renderContent()
49
60
 
50
61
  open fun render() {
62
+ setUpViews()
51
63
  renderContent()
52
64
  }
53
65
 
package/ios/RNSmileID.mm CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  @interface RCT_EXTERN_MODULE(RNSmileID, NSObject)
4
4
  RCT_EXTERN_METHOD(initialize:(BOOL)useSandBox withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
5
+ RCT_EXTERN_METHOD(authenticate:(NSDictionary *)request withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
6
+ RCT_EXTERN_METHOD(prepUpload:(NSDictionary *)request withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
7
+ RCT_EXTERN_METHOD(upload:(NSString *)url request:(NSDictionary *)request withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
5
8
  RCT_EXTERN_METHOD(doEnhancedKyc:(NSDictionary *)request withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
6
9
  RCT_EXTERN_METHOD(doEnhancedKycAsync:(NSDictionary *)request withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
10
+ RCT_EXTERN_METHOD(getSmartSelfieJobStatus:(NSDictionary *)request withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
11
+ RCT_EXTERN_METHOD(getDocumentVerificationJobStatus:(NSDictionary *)request withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
12
+ RCT_EXTERN_METHOD(getBiometricKycJobStatus:(NSDictionary *)request withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
13
+ RCT_EXTERN_METHOD(getEnhancedDocumentVerificationJobStatus:(NSDictionary *)request withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
14
+ RCT_EXTERN_METHOD(getProductsConfig:(NSDictionary *)request withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
15
+ RCT_EXTERN_METHOD(getValidDocuments:(NSDictionary *)request withResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
16
+ RCT_EXTERN_METHOD(getServicesWithResolver:(RCTPromiseResolveBlock)resolve withRejecter:(RCTPromiseRejectBlock)reject)
7
17
  @end
@@ -11,6 +11,58 @@ class RNSmileID: NSObject {
11
11
  resolve(nil)
12
12
  }
13
13
 
14
+ @objc(authenticate:withResolver:withRejecter:)
15
+ func authenticate(request: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
16
+ guard let authenticationRequest = request.toAuthenticationRequest() else {
17
+ reject("Error", "Invalid request data", nil)
18
+ return
19
+ }
20
+
21
+ SmileID.api.authenticate(request: authenticationRequest)
22
+ .sink(receiveCompletion: { completion in
23
+ self.handleCompletion(completion, reject: reject)
24
+ }, receiveValue: { response in
25
+ self.resolveResponse(response, resolve: resolve, reject: reject)
26
+ }).store(in: &cancellables)
27
+ }
28
+
29
+ @objc(prepUpload:withResolver:withRejecter:)
30
+ func prepUpload(request: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
31
+ guard let prepUploadRequest = request.toPrepUploadRequest() else {
32
+ reject("Error", "Invalid prep upload request", nil)
33
+ return
34
+ }
35
+
36
+ SmileID.api.prepUpload(request: prepUploadRequest)
37
+ .sink(
38
+ receiveCompletion: { completion in self.handleCompletion(completion, reject: reject) },
39
+ receiveValue: { response in self.resolveResponse(response, resolve: resolve, reject: reject)
40
+ }).store(in: &cancellables)
41
+ }
42
+
43
+ @objc(upload:request:withResolver:withRejecter:)
44
+ func upload(url: String, request: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
45
+ guard let uploadRequest = request.toUploadRequest() else {
46
+ reject("Error", "Invalid upload request", nil)
47
+ return
48
+ }
49
+
50
+ guard let zipUrl = try? LocalStorage.toZip(uploadRequest: uploadRequest) else {
51
+ reject("Error", "Unable to zip file", nil)
52
+ return
53
+ }
54
+
55
+ guard let zipData = try? Data(contentsOf: zipUrl) else {
56
+ reject("Error", "Unable to read zip file", nil)
57
+ return
58
+ }
59
+
60
+ SmileID.api.upload(zip: zipData, to: url)
61
+ .sink(receiveCompletion: { completion in self.handleCompletion(completion, reject: reject) },
62
+ receiveValue: { _ in resolve(nil) }) // Assuming no response to return
63
+ .store(in: &cancellables)
64
+ }
65
+
14
66
  @objc(doEnhancedKyc:withResolver:withRejecter:)
15
67
  func doEnhancedKyc(request: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
16
68
  guard let partnerParamsDict = request["partnerParams"] as? NSDictionary else {
@@ -144,4 +196,89 @@ class RNSmileID: NSObject {
144
196
  resolve(["result": String(data: jsonData, encoding: .utf8)!]) // Assuming you have a method to convert response to a dictionary
145
197
  }).store(in: &cancellables)
146
198
  }
199
+
200
+ @objc(getSmartSelfieJobStatus:withResolver:withRejecter:)
201
+ func getSmartSelfieJobStatus(request: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
202
+ getJobStatus(request: request, resolve: resolve, reject: reject)
203
+ }
204
+
205
+ @objc(getDocumentVerificationJobStatus:withResolver:withRejecter:)
206
+ func getDocumentVerificationJobStatus(request: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
207
+ getJobStatus(request: request, resolve: resolve, reject: reject)
208
+ }
209
+
210
+ @objc(getBiometricKycJobStatus:withResolver:withRejecter:)
211
+ func getBiometricKycJobStatus(request: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
212
+ getJobStatus(request: request, resolve: resolve, reject: reject)
213
+ }
214
+
215
+ @objc(getEnhancedDocumentVerificationJobStatus:withResolver:withRejecter:)
216
+ func getEnhancedDocumentVerificationJobStatus(request: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
217
+ getJobStatus(request: request, resolve: resolve, reject: reject)
218
+ }
219
+
220
+ @objc(getProductsConfig:withResolver:withRejecter:)
221
+ func getProductsConfig(request: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
222
+ guard let productsConfigRequest = request.toProductsConfigRequest() else {
223
+ reject("Error", "Invalid products config request", nil)
224
+ return
225
+ }
226
+
227
+ SmileID.api.getProductsConfig(request: productsConfigRequest)
228
+ .sink(
229
+ receiveCompletion: { completion in self.handleCompletion(completion, reject: reject) },
230
+ receiveValue: { response in self.resolveResponse(response, resolve: resolve, reject: reject)
231
+ }).store(in: &cancellables)
232
+ }
233
+
234
+ @objc(getValidDocuments:withResolver:withRejecter:)
235
+ func getValidDocuments(request: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
236
+ guard let validDocumentsRequest = request.toProductsConfigRequest() else {
237
+ reject("Error", "Invalid valid documents request", nil)
238
+ return
239
+ }
240
+
241
+ SmileID.api.getValidDocuments(request: validDocumentsRequest)
242
+ .sink(receiveCompletion: { completion in self.handleCompletion(completion, reject: reject) },
243
+ receiveValue: { response in self.resolveResponse(response, resolve: resolve, reject: reject) })
244
+ .store(in: &cancellables)
245
+ }
246
+
247
+ @objc(getServicesWithResolver:withRejecter:)
248
+ func getServices(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
249
+ SmileID.api.getServices()
250
+ .sink(receiveCompletion: { completion in self.handleCompletion(completion, reject: reject) },
251
+ receiveValue: { response in self.resolveResponse(response, resolve: resolve, reject: reject) })
252
+ .store(in: &cancellables)
253
+ }
254
+
255
+ private func getJobStatus(request: NSDictionary, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
256
+ guard let jobStatusRequest = request.toJobStatusRequest() else {
257
+ reject("Error", "Invalid job status request", nil)
258
+ return
259
+ }
260
+
261
+ SmileID.api.getJobStatus(request: jobStatusRequest)
262
+ .sink(receiveCompletion: { completion in self.handleCompletion(completion, reject: reject) },
263
+ receiveValue: { response in self.resolveResponse(response, resolve: resolve, reject: reject) })
264
+ .store(in: &cancellables)
265
+ }
266
+
267
+ private func handleCompletion(_ completion: Subscribers.Completion<Error>, reject: @escaping RCTPromiseRejectBlock) {
268
+ switch completion {
269
+ case let .failure(error):
270
+ reject("Error", error.localizedDescription, error)
271
+ case .finished:
272
+ break
273
+ }
274
+ }
275
+
276
+ private func resolveResponse<T: Encodable>(_ response: T, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
277
+ let encoder = JSONEncoder()
278
+ guard let jsonData = try? encoder.encode(response) else {
279
+ reject("Error", "Encoding error", nil)
280
+ return
281
+ }
282
+ resolve(String(data: jsonData, encoding: .utf8) ?? "")
283
+ }
147
284
  }
@@ -2,18 +2,85 @@ import Foundation
2
2
  import SmileID
3
3
 
4
4
  extension NSDictionary {
5
+ func toAuthenticationRequest() -> AuthenticationRequest? {
6
+ guard let jobTypeValue = self["jobType"] as? Int,
7
+ let jobType = JobType(rawValue: jobTypeValue),
8
+ let country = self["country"] as? String,
9
+ let idType = self["idType"] as? String,
10
+ let updateEnrolledImage = self["updateEnrolledImage"] as? Bool,
11
+ let jobId = self["jobId"] as? String,
12
+ let userId = self["userId"] as? String else {
13
+ return nil
14
+ }
15
+
16
+ return AuthenticationRequest(
17
+ jobType: jobType,
18
+ updateEnrolledImage: updateEnrolledImage,
19
+ jobId: jobId,
20
+ userId: userId,
21
+ country: country,
22
+ idType: idType
23
+ )
24
+ }
25
+
26
+ func toPrepUploadRequest() -> PrepUploadRequest? {
27
+ guard let partnerParamsDict = self["partnerParams"] as? NSDictionary,
28
+ let partnerParams = partnerParamsDict.toPartnerParams(),
29
+ let callbackUrl = self["callbackUrl"] as? String,
30
+ let partnerId = self["partnerId"] as? String,
31
+ let timestamp = self["timestamp"] as? String,
32
+ let signature = self["signature"] as? String else {
33
+ return nil
34
+ }
35
+
36
+ return PrepUploadRequest(
37
+ partnerParams: partnerParams,
38
+ callbackUrl: callbackUrl,
39
+ partnerId: partnerId,
40
+ sourceSdk: self["sourceSdk"] as? String ?? "ios (react-native)",
41
+ timestamp: timestamp,
42
+ signature: signature
43
+ )
44
+ }
45
+
46
+ func toUploadRequest() -> UploadRequest? {
47
+ guard let imagesArray = self["images"] as? [NSDictionary] else {
48
+ return nil
49
+ }
50
+ let images = imagesArray.compactMap { $0.toUploadImageInfo() }
51
+ let idInfo = (self["idInfo"] as? NSDictionary)?.toIdInfo()
52
+
53
+ return UploadRequest(
54
+ images: images,
55
+ idInfo: idInfo
56
+ )
57
+ }
58
+
59
+ func toUploadImageInfo() -> UploadImageInfo? {
60
+ guard let imageTypeIdValue = self["imageTypeId"] as? String,
61
+ let imageTypeId = ImageType(rawValue: imageTypeIdValue),
62
+ let imageName = self["imageName"] as? String else {
63
+ return nil
64
+ }
65
+
66
+ return UploadImageInfo(
67
+ imageTypeId: imageTypeId,
68
+ fileName: imageName
69
+ )
70
+ }
71
+
5
72
  func toIdInfo() -> IdInfo? {
6
73
  guard let country = self["country"] as? String else {
7
74
  return nil
8
75
  }
9
76
 
10
- let idType = self["id_type"] as? String
11
- let idNumber = self["id_number"] as? String
12
- let firstName = self["first_name"] as? String
13
- let middleName = self["middle_name"] as? String
14
- let lastName = self["last_name"] as? String
77
+ let idType = self["idType"] as? String
78
+ let idNumber = self["idNumber"] as? String
79
+ let firstName = self["firstName"] as? String
80
+ let middleName = self["middleName"] as? String
81
+ let lastName = self["lastName"] as? String
15
82
  let dob = self["dob"] as? String
16
- let bankCode = self["bank_code"] as? String
83
+ let bankCode = self["bankCode"] as? String
17
84
  let entered = self["entered"] as? Bool
18
85
 
19
86
  return IdInfo(
@@ -29,6 +96,78 @@ extension NSDictionary {
29
96
  )
30
97
  }
31
98
 
99
+ func toEnhancedKycRequest() -> EnhancedKycRequest? {
100
+ guard let country = self["country"] as? String,
101
+ let idType = self["idType"] as? String,
102
+ let idNumber = self["idNumber"] as? String,
103
+ let firstName = self["firstName"] as? String,
104
+ let middleName = self["middleName"] as? String,
105
+ let lastName = self["lastName"] as? String,
106
+ let dob = self["dob"] as? String,
107
+ let phoneNumber = self["phoneNumber"] as? String,
108
+ let bankCode = self["bankCode"] as? String,
109
+ let callbackUrl = self["callbackUrl"] as? String,
110
+ let partnerParamsDict = self["partnerParams"] as? NSDictionary,
111
+ let partnerParams = partnerParamsDict.toPartnerParams(),
112
+ let timestamp = self["timestamp"] as? String,
113
+ let signature = self["signature"] as? String else {
114
+ return nil
115
+ }
116
+
117
+ return EnhancedKycRequest(
118
+ country: country,
119
+ idType: idType,
120
+ idNumber: idNumber,
121
+ firstName: firstName,
122
+ middleName: middleName,
123
+ lastName: lastName,
124
+ dob: dob,
125
+ phoneNumber: phoneNumber,
126
+ bankCode: bankCode,
127
+ callbackUrl: callbackUrl,
128
+ partnerParams: partnerParams,
129
+ sourceSdk: self["sourceSdk"] as? String ?? "ios (react-native)",
130
+ timestamp: timestamp,
131
+ signature: signature
132
+ )
133
+ }
134
+
135
+ func toJobStatusRequest() -> JobStatusRequest? {
136
+ guard let userId = self["userId"] as? String,
137
+ let jobId = self["jobId"] as? String,
138
+ let includeImageLinks = self["includeImageLinks"] as? Bool,
139
+ let includeHistory = self["includeHistory"] as? Bool,
140
+ let partnerId = self["partnerId"] as? String,
141
+ let timestamp = self["timestamp"] as? String,
142
+ let signature = self["signature"] as? String else {
143
+ return nil
144
+ }
145
+
146
+ return JobStatusRequest(
147
+ userId: userId,
148
+ jobId: jobId,
149
+ includeImageLinks: includeImageLinks,
150
+ includeHistory: includeHistory,
151
+ partnerId: partnerId,
152
+ timestamp: timestamp,
153
+ signature: signature
154
+ )
155
+ }
156
+
157
+ func toProductsConfigRequest() -> ProductsConfigRequest? {
158
+ guard let partnerId = self["partnerId"] as? String,
159
+ let timestamp = self["timestamp"] as? String,
160
+ let signature = self["signature"] as? String else {
161
+ return nil
162
+ }
163
+
164
+ return ProductsConfigRequest(
165
+ timestamp: timestamp,
166
+ signature: signature,
167
+ partnerId: partnerId
168
+ )
169
+ }
170
+
32
171
  func toPartnerParams() -> PartnerParams? {
33
172
  guard let country = self["country"] as? String else {
34
173
  return nil
@@ -4,18 +4,33 @@ import SwiftUI
4
4
  class BaseSmileIDView: UIView {
5
5
  typealias ContentView = AnyView
6
6
  var contentView : AnyView?
7
-
8
- init(frame: CGRect,contentView:AnyView) {
7
+ private var _onResult: RCTBubblingEventBlock?
8
+ var product : SmileIDProductModel?
9
+
10
+ @objc var onResult: RCTBubblingEventBlock? {
11
+ get {
12
+ return _onResult
13
+ }
14
+ set {
15
+ _onResult = newValue
16
+ if newValue != nil {
17
+ product?.onResult = newValue
18
+ }
19
+ }
20
+ }
21
+
22
+ init(frame: CGRect,contentView:AnyView,product:SmileIDProductModel) {
9
23
  self.contentView = contentView
24
+ self.product = product
10
25
  super.init(frame: frame)
11
26
  commonInit()
12
27
  }
13
-
28
+
14
29
  required init?(coder aDecoder: NSCoder) {
15
30
  super.init(coder: aDecoder)
16
31
  commonInit()
17
32
  }
18
-
33
+
19
34
  private func commonInit() {
20
35
  // Perform initialization tasks here
21
36
  // For example, setup subviews, add constraints, configure appearance
@@ -28,8 +43,10 @@ class BaseSmileIDView: UIView {
28
43
  hostingView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
29
44
  hostingView.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
30
45
  }
31
-
46
+
32
47
  func getView(product:SmileIDProductModel) -> AnyView {
33
48
  fatalError("Must be implemented by subclass")
34
49
  }
50
+
51
+
35
52
  }