package io.caf.faceliveness import com.caf.facelivenessiproov.input.ErrorType import com.caf.facelivenessiproov.input.FaceLiveness import com.caf.facelivenessiproov.input.SdkPlatform import com.caf.facelivenessiproov.input.VerifyLivenessListener import com.caf.facelivenessiproov.output.FaceLivenessFailureResult import com.caf.facelivenessiproov.output.FaceLivenessResult import com.caf.facelivenessiproov.output.failure.SDKError import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.ReactContextBaseJavaModule import com.facebook.react.bridge.ReactMethod import com.facebook.react.bridge.WritableNativeMap import com.facebook.react.modules.core.DeviceEventManagerModule import javax.annotation.Nonnull class CafFaceLiveness(private val reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { @Nonnull override fun getName(): String { return CAF_FACE_LIVENESS } @ReactMethod fun startFaceLiveness(mobileToken: String, personId: String, config: String) { val cafFaceLivenessConfig = CafFaceLivenessConfig(config) val faceLiveness: FaceLiveness.Builder = FaceLiveness.Builder(mobileToken) .setSdkIdentifier(CAF_SDK_IDENTIFIER) .setSdkPlatform(SdkPlatform.REACT_NATIVE) cafFaceLivenessConfig.cafStage?.let { faceLiveness.setStage(it) } cafFaceLivenessConfig.filter?.let { faceLiveness.setFilter(it) } cafFaceLivenessConfig.enableScreenshots?.let { faceLiveness.setEnableScreenshots(it) } cafFaceLivenessConfig.loadingScreen?.let { faceLiveness.setLoadingScreen(it) } cafFaceLivenessConfig.imageUrlExpirationTime?.let { faceLiveness.setImageUrlExpirationTime(it) } cafFaceLivenessConfig.faceLivenessBaseUrl?.let { faceLiveness.setFaceLivenessBaseUrl(it) } cafFaceLivenessConfig.authenticationBaseUrl?.let { faceLiveness.setAuthenticationBaseUrl(it) } cafFaceLivenessConfig.certificates?.let { faceLiveness.setCertificates(it.toTypedArray()) } faceLiveness.build().startSDK(reactContext, personId, object : VerifyLivenessListener { override fun onSuccess(faceLivenessResult: FaceLivenessResult?) { val writableMap = WritableNativeMap().apply { putString(CAF_WRITABLE_MAP_SIGNED_RESPONSE, faceLivenessResult?.signedResponse) } reactApplicationContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(CAF_FACE_LIVENESS_SUCCESS_EVENT, writableMap) } override fun onFailure(result: FaceLivenessFailureResult?) { val writableMap = WritableNativeMap() writableMap.apply { putString(CAF_WRITABLE_MAP_SIGNED_RESPONSE, result?.signedResponse) putString(CAF_WRITABLE_MAP_ERROR_MESSAGE, result?.failureMessage) putString(CAF_WRITABLE_MAP_ERROR_TYPE, result?.failureType) } reactApplicationContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(CAF_FACE_LIVENESS_FAILURE_EVENT, writableMap) } override fun onError(sdkFailure: SDKError?) { val writableMap = WritableNativeMap() val (message, type) = when (sdkFailure?.errorType) { ErrorType.TOKEN_EXCEPTION -> CAF_MESSAGE_TOKEN_EXCEPTION to CAF_TYPE_TOKEN_EXCEPTION ErrorType.CAMERA_PERMISSION -> CAF_MESSAGE_CAMERA_PERMISSION to CAF_TYPE_CAMERA_PERMISSION ErrorType.NETWORK_EXCEPTION -> CAF_MESSAGE_NETWORK_EXCEPTION to CAF_TYPE_NETWORK_EXCEPTION ErrorType.SERVER_EXCEPTION -> CAF_MESSAGE_SERVER_EXCEPTION to CAF_TYPE_SERVER_EXCEPTION ErrorType.UNSUPPORTED_DEVICE -> CAF_MESSAGE_UNSUPPORTED_DEVICE to CAF_TYPE_UNSUPPORTED_DEVICE ErrorType.CERTIFICATE_EXCEPTION -> sdkFailure.description to CAF_TYPE_CERTIFICATE_EXCEPTION ErrorType.MULTI_WINDOW_UNSUPPORTED_EXCEPTION -> sdkFailure.description to CAF_MULTI_WINDOW_UNSUPPORTED_EXCEPTION ErrorType.CAPTURE_ALREADY_ACTIVE_EXCEPTION -> sdkFailure.description to CAF_TYPE_CAPTURE_ALREADY_ACTIVE_EXCEPTION ErrorType.CAMERA_EXCEPTION -> sdkFailure.description to CAF_TYPE_CAMERA_EXCEPTION ErrorType.FACE_DETECTOR_EXCEPTION -> sdkFailure.description to CAF_TYPE_FACE_DETECTOR_EXCEPTION ErrorType.UNEXPECTED_ERROR_EXCEPTION -> sdkFailure.description to CAF_TYPE_UNEXPECTED_ERROR_EXCEPTION ErrorType.INVALID_OPTIONS_EXCEPTION -> sdkFailure.description to CAF_TYPE_INVALID_OPTIONS_EXCEPTION ErrorType.IMAGE_NOT_FOUND_EXCEPTION -> sdkFailure.description to CAF_TYPE_IMAGE_NOT_FOUND_EXCEPTION ErrorType.TOO_MANY_REQUESTS_EXCEPTION -> sdkFailure.description to CAF_TYPE_TOO_MANY_REQUESTS_EXCEPTION else -> CAF_MESSAGE_UNKNOWN_EXCEPTION to CAF_TYPE_UNKNOWN_EXCEPTION } writableMap.apply { putString(CAF_WRITABLE_MAP_ERROR_MESSAGE, message) putString(CAF_WRITABLE_MAP_ERROR_TYPE, type) } reactApplicationContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(CAF_FACE_LIVENESS_ERROR_EVENT, writableMap) } override fun onCancel() { reactApplicationContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(CAF_FACE_LIVENESS_CANCELLED_EVENT, true) } override fun onLoading() { reactApplicationContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(CAF_FACE_LIVENESS_LOADING_EVENT, true) } override fun onLoaded() { reactApplicationContext .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java) .emit(CAF_FACE_LIVENESS_LOADED_EVENT, true) } }) } private companion object { const val CAF_FACE_LIVENESS = "CafFaceLiveness" const val CAF_SDK_IDENTIFIER = "face-liveness" const val CAF_FACE_LIVENESS_SUCCESS_EVENT = "FaceLiveness_Success" const val CAF_FACE_LIVENESS_ERROR_EVENT = "FaceLiveness_Error" const val CAF_FACE_LIVENESS_FAILURE_EVENT = "FaceLiveness_Failure" const val CAF_FACE_LIVENESS_CANCELLED_EVENT = "FaceLiveness_Cancelled" const val CAF_FACE_LIVENESS_LOADING_EVENT = "FaceLiveness_Loading" const val CAF_FACE_LIVENESS_LOADED_EVENT = "FaceLiveness_Loaded" const val CAF_MESSAGE_TOKEN_EXCEPTION = "Internal Server Error" const val CAF_MESSAGE_CAMERA_PERMISSION = "Camera Permission Denied" const val CAF_MESSAGE_NETWORK_EXCEPTION = "Service Unavailable" const val CAF_MESSAGE_SERVER_EXCEPTION = "Internal Server Error" const val CAF_MESSAGE_UNSUPPORTED_DEVICE = "Device Not Supported" const val CAF_MESSAGE_UNKNOWN_EXCEPTION = "Unknown Error: contact support" const val CAF_TYPE_TOKEN_EXCEPTION = "TokenException" const val CAF_TYPE_CAMERA_PERMISSION = "CameraPermission" const val CAF_TYPE_NETWORK_EXCEPTION = "NetworkException" const val CAF_TYPE_SERVER_EXCEPTION = "ServerException" const val CAF_TYPE_UNSUPPORTED_DEVICE = "UnsupportedDevice" const val CAF_TYPE_CERTIFICATE_EXCEPTION = "CertificateException" const val CAF_TYPE_CAMERA_EXCEPTION = "CameraException" const val CAF_MULTI_WINDOW_UNSUPPORTED_EXCEPTION = "MultiWindowUnsupportedException" const val CAF_TYPE_CAPTURE_ALREADY_ACTIVE_EXCEPTION = "CaptureAlreadyActiveException" const val CAF_TYPE_FACE_DETECTOR_EXCEPTION = "FaceDetectorException" const val CAF_TYPE_UNEXPECTED_ERROR_EXCEPTION = "UnexpectedErrorException" const val CAF_TYPE_INVALID_OPTIONS_EXCEPTION = "InvalidOptionsException" const val CAF_TYPE_IMAGE_NOT_FOUND_EXCEPTION = "ImageNotFoundException" const val CAF_TYPE_TOO_MANY_REQUESTS_EXCEPTION = "TooManyRequestsException" const val CAF_TYPE_UNKNOWN_EXCEPTION = "UnknownException" const val CAF_WRITABLE_MAP_SIGNED_RESPONSE = "signedResponse" const val CAF_WRITABLE_MAP_ERROR_MESSAGE = "message" const val CAF_WRITABLE_MAP_ERROR_TYPE = "type" } }