Feature/digio adhaar verification (#248)

* digio adhar verification

* started working...

* path changed

*  model name change

* aadhar verification flow

* api changes

* path modifivcation

* api modification

* removed unsued code

* removed build folder

* hiding loader incase polling for observeAadharVerificationStatus

* minor changes
This commit is contained in:
Satish Prasad
2020-02-13 12:59:35 +05:30
committed by GitHub Enterprise
parent ed3fc76733
commit 53f719e668
17 changed files with 245 additions and 31 deletions

View File

@@ -108,6 +108,11 @@ dependencies {
// Add the Firebase SDK for Google Analytics
implementation 'com.google.firebase:firebase-analytics:17.2.2'
//Digio: for adhaar verification
implementation project(":digio-kyc-1.0.0")
// implementation 'com.squareup.okhttp3:okhttp:4.2.1'
// AndroidJUnitRunner and JUnit Rules
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'

View File

@@ -89,6 +89,13 @@
android:screenOrientation="portrait"
android:theme="@style/BaseThemeStyle" />
<!-- For Digio, Adhaar verification -->
<activity
android:name="in.digio.sdk.kyc.DigioMainActivity"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize" />
<!-- For Digio, Adhaar verification END -->
<!-- NaviFirebaseMessagingService is for firebase push notification -->
<service
android:name=".pushnotification.firebase.NaviFirebaseMessagingService"
@@ -106,7 +113,9 @@
android:value="false" />
<meta-data
android:name="firebase_analytics_collection_enabled"
android:value="false" /> <!-- for Appsflyer install tracking -->
android:value="false" />
<!-- for Appsflyer install tracking -->
<receiver
android:name="com.appsflyer.SingleInstallBroadcastReceiver"
android:exported="true">

View File

@@ -18,3 +18,4 @@ const val UPDATE_KYC_DETAILS = "UPDATE_KYC_DETAILS"
const val OFFER_GENERATE = "OFFER_GENERATE"
const val LOAN_APPLY = "LOAN_APPLY"
const val ADD_BANK_ACCOUNT = "ADD_BANK_ACCOUNT"
const val AADHAR_VERIFICATION = "AADHAR_VERIFICATION"

View File

@@ -54,6 +54,7 @@ class FirebaseDataHelper {
UPDATE_KYC_DETAILS -> "UPDATE_KYC_DETAILS"
OFFER_GENERATE -> "GENERATE_OFFER"
LOAN_APPLY -> "APPLY_LOAN"
AADHAR_VERIFICATION -> "AADHAR_VERIFICATION"
else -> null
}
}

View File

@@ -11,9 +11,9 @@ import androidx.annotation.StringDef
object FirebaseStatusType {
const val SUCCESS = "SUCCESS"
const val ERROR = "ERROR"
const val FAILURE = "FAILURE"
@StringDef(SUCCESS, ERROR)
@StringDef(SUCCESS, FAILURE)
@Retention(AnnotationRetention.SOURCE)
annotation class FirebaseStatusTypeDef
}

View File

@@ -3,12 +3,15 @@ package com.navi.getloan.activities
import android.os.Bundle
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProviders
import com.navi.R
import com.navi.common.BaseActivity
import com.navi.dashboard.listeners.FragmentInteractionListener
import com.navi.databinding.ActivityGetLoanBinding
import com.navi.firebasedb.FirebaseStatusType
import com.navi.getloan.bankdetails.fragments.BankDetailsFragment
import com.navi.getloan.kyc.fragments.KycFragment
import com.navi.getloan.kyc.viewmodels.KycSharedVM
import com.navi.getloan.loanagreement.fragments.LoanAgreementFragment
import com.navi.getloan.loandetails.fragments.LoanDetailsFragment
import com.navi.useridentification.activities.LoanEligibilityLoaderActivity.Companion.OFFER
@@ -17,6 +20,7 @@ import com.navi.useridentification.common.FormProgressBar
class GetLoanActivity : BaseActivity(), FragmentInteractionListener,
FormProgressBar.FormProgressListener {
private lateinit var binding: ActivityGetLoanBinding
private val viewModel by lazy { ViewModelProviders.of(this).get(KycSharedVM::class.java) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -96,6 +100,14 @@ class GetLoanActivity : BaseActivity(), FragmentInteractionListener,
}
}
fun onDigioKycSuccess(documentId: String, message: String) {
viewModel.setAadharResponseStatus(documentId, FirebaseStatusType.SUCCESS)
}
fun onDigioKycFailure(documentId: String, message: String) {
viewModel.setAadharResponseStatus(documentId, FirebaseStatusType.FAILURE)
}
override val screenName: String
get() = TAG

View File

@@ -20,20 +20,15 @@ import com.navi.common.ApiPollScheduler
import com.navi.common.BaseFragment
import com.navi.dashboard.listeners.FragmentInteractionListener
import com.navi.databinding.KycFragmentBinding
import com.navi.firebasedb.FirebaseDataHelper
import com.navi.firebasedb.FirebaseDataReceiveListener
import com.navi.firebasedb.FirebaseResponse
import com.navi.firebasedb.FirebaseStatusType
import com.navi.firebasedb.SELFIE
import com.navi.firebasedb.UPDATE_KYC_DETAILS
import com.navi.firebasedb.*
import com.navi.getloan.activities.GetLoanActivity.Companion.BANK_DETAILS_SCREEN
import com.navi.getloan.activities.GetLoanActivity.Companion.SHOULD_SET_PROGRESS
import com.navi.getloan.kyc.activities.SelfieCaptureActivity
import com.navi.getloan.kyc.listeners.DocumentUploadListener
import com.navi.getloan.kyc.viewmodels.KycSharedVM
import com.navi.getloan.kyc.viewmodels.KycVM
import com.navi.utils.Constants
import com.navi.utils.isDead
import com.navi.utils.observeNonNull
import com.navi.kyc.adharverification.digio.AdharVerificationHelper
import com.navi.utils.*
import java.io.ByteArrayOutputStream
import java.io.FileInputStream
@@ -60,6 +55,13 @@ class KycFragment : BaseFragment(), RadioGroup.OnCheckedChangeListener, View.OnC
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
activity?.let {
val sharedViewModel = ViewModelProviders.of(it).get(KycSharedVM::class.java)
observeAadharVerificationStatus(sharedViewModel)
}
}
private fun initListeners() {
binding.selfieLl.setOnClickListener(this)
observeSelfieAsyncData()
@@ -70,13 +72,39 @@ class KycFragment : BaseFragment(), RadioGroup.OnCheckedChangeListener, View.OnC
binding.nextBtn.setOnClickListener(this)
binding.aadhaarLayout.addressLayout.uploadLl.setOnClickListener(this)
binding.aadhaarLayout.addressLayout.billTypeLl.setOnClickListener(this)
binding.aadhaarLayout.root.setOnClickListener { setVisibilityOfAddressLayout() }
binding.aadhaarLayout.root.setOnClickListener { handleAadharClick() }
observeKycDetailsSubmissionAsyncData()
observeKycVerificationStatus()
}
private fun setVisibilityOfAddressLayout() {
binding.aadhaarLayout.addressLayout.root.visibility = View.VISIBLE
private fun handleAadharClick() {
activity?.let {
observeAdharVerificationData()
viewModel.initVerification()
}
}
private fun observeAadharVerificationStatus(sharedVM: KycSharedVM) {
viewModel.aadharVerificationStatusResponse.observeNullable(this) { data ->
data?.requestId?.let {
showLoader()
firebaseInit(it, AADHAR_VERIFICATION)
observerAsyncData(AADHAR_VERIFICATION)
apiPollInit(it, AADHAR_VERIFICATION)
}
}
sharedVM.aadharVerificationResponse.observeNullable(this) { data ->
data?.let {
viewModel.fetchAadharVerificationStatusData(it)
}
}
}
private fun observerAsyncData(type: String) {
viewModel.dataAsyncResponse.observeNullable(this) {
if (TextUtils.equals(it?.status, FirebaseStatusType.SUCCESS)) hideLoader()
handleFirebaseResult(it?.status.orEmpty(), type)
}
}
private fun initUi() {
@@ -169,7 +197,8 @@ class KycFragment : BaseFragment(), RadioGroup.OnCheckedChangeListener, View.OnC
override fun onDataReceive(firebaseResponse: FirebaseResponse?) {
firebaseResponse?.let {
apiPollScheduler?.stopApiPoll()
handleFirebaseResult(it, requestId, type)
hideLoader()
handleFirebaseResult(it.status.orEmpty(), type)
}
}
}
@@ -184,25 +213,29 @@ class KycFragment : BaseFragment(), RadioGroup.OnCheckedChangeListener, View.OnC
}
private fun handleFirebaseResult(
firebaseResponse: FirebaseResponse,
requestId: String,
status: String,
type: String
) {
when (type) {
SELFIE -> {
if (TextUtils.equals(
firebaseResponse.status,
status,
FirebaseStatusType.SUCCESS
)
) onSelfieUploadSuccess()
}
UPDATE_KYC_DETAILS -> {
if (TextUtils.equals(
firebaseResponse.status,
status,
FirebaseStatusType.SUCCESS
)
) openAadhaarVerification()
}
AADHAR_VERIFICATION -> {
if (TextUtils.equals(status, FirebaseStatusType.SUCCESS)) {
binding.aadhaarLayout.addressLayout.root.visibility = View.VISIBLE
}
}
}
}
@@ -236,10 +269,24 @@ class KycFragment : BaseFragment(), RadioGroup.OnCheckedChangeListener, View.OnC
private fun apiPollInit(requestId: String, type: String) {
apiPollScheduler = ApiPollScheduler {
viewModel.checkApiPollStatus(requestId, type)
}
}
apiPollScheduler?.scheduleApiPoll()
}
private fun observeAdharVerificationData() {
viewModel.initVerificationData.observeNullable(this) { data ->
if (data?.aadharRequestId?.isNotBlank().orFalse()) {
activity?.let {
AdharVerificationHelper().initConfig(
it,
data?.aadharRequestId.orEmpty(),
data?.aadharIdentifier.orEmpty()
)
}
}
}
}
private fun openAadhaarVerification() {
viewModel.fetchKycStatus()
}
@@ -296,7 +343,6 @@ class KycFragment : BaseFragment(), RadioGroup.OnCheckedChangeListener, View.OnC
)
}
private fun navigateToBankDetailsScreen() {
listener?.navigateTo(BANK_DETAILS_SCREEN, Bundle().apply {
putBoolean(SHOULD_SET_PROGRESS, true)
@@ -332,4 +378,4 @@ class KycFragment : BaseFragment(), RadioGroup.OnCheckedChangeListener, View.OnC
private const val COMPLETE = "complete"
private const val PENDING = "pending"
}
}
}

View File

@@ -0,0 +1,14 @@
/*
* *
* * Copyright (c) 2020 . All rights reserved @Navi
*
*/
package com.navi.getloan.kyc.models
import com.google.gson.annotations.SerializedName
data class AadharVerificationStatusData(
@SerializedName("aadharRequestId") val aadharRequestId: String? = null,
@SerializedName("status") val status: String? = null
)

View File

@@ -0,0 +1,14 @@
/*
* *
* * Copyright (c) 2020 . All rights reserved @Navi
*
*/
package com.navi.getloan.kyc.models
import com.google.gson.annotations.SerializedName
data class InitVerificationResponse(
@SerializedName("aadharRequestId") val aadharRequestId: String? = null,
@SerializedName("aadharIdentifier") var aadharIdentifier: String? = null
)

View File

@@ -1,6 +1,7 @@
package com.navi.getloan.kyc.repositories
import com.google.gson.reflect.TypeToken
import com.navi.getloan.kyc.models.AadharVerificationStatusData
import com.navi.models.request.KycRequest
import com.navi.models.response.KycUploadResponse
import com.navi.models.response.KycVerificationResponse
@@ -37,8 +38,15 @@ class KycRepository : ResponseCallback() {
}
suspend fun fetchAsyncRequestData(requestId: String): RepoResult<UploadDataAsyncResponse> {
// apiResponseCallback(retrofitService().fetchAsyncRequestData(requestId))
val type = object : TypeToken<UploadDataAsyncResponse>() {}.type
return mockApiResponse(type, "async")
return apiResponseCallback(retrofitService().fetchAsyncRequestData(requestId))
// val type = object : TypeToken<UploadDataAsyncResponse>() {}.type
// return mockApiResponse(type, "async")
}
suspend fun initVerification() =
apiResponseCallback(retrofitService().initiateAdharVerification())
suspend fun fetchAadharVerificationStatus(data: AadharVerificationStatusData) =
apiResponseCallback(retrofitService().fetchVerificationStatus(data))
}

View File

@@ -0,0 +1,23 @@
/*
* *
* * Copyright (c) 2020 . All rights reserved @Navi
*
*/
package com.navi.getloan.kyc.viewmodels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.navi.getloan.kyc.models.AadharVerificationStatusData
class KycSharedVM : ViewModel() {
private val _aadharVerificationResponse = MutableLiveData<AadharVerificationStatusData>()
val aadharVerificationResponse: LiveData<AadharVerificationStatusData>
get() = _aadharVerificationResponse
fun setAadharResponseStatus(documentId: String, status: String) {
_aadharVerificationResponse.value = AadharVerificationStatusData(documentId, status)
}
}

View File

@@ -3,9 +3,13 @@ package com.navi.getloan.kyc.viewmodels
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.navi.common.BaseVM
import com.navi.firebasedb.AADHAR_VERIFICATION
import com.navi.firebasedb.SELFIE
import com.navi.firebasedb.UPDATE_KYC_DETAILS
import com.navi.getloan.kyc.models.AadharVerificationStatusData
import com.navi.getloan.kyc.models.InitVerificationResponse
import com.navi.getloan.kyc.repositories.KycRepository
import com.navi.manager.UserManager
import com.navi.models.request.Address
import com.navi.models.request.KycRequest
import com.navi.models.request.ParentDetails
@@ -35,11 +39,18 @@ class KycVM : BaseVM() {
val kycDetailsSubmitAsyncData: LiveData<UploadDataAsyncResponse>
get() = _kycDetailsSubmitAsyncData
private val _initVerificationData = MutableLiveData<InitVerificationResponse>()
val initVerificationData: LiveData<InitVerificationResponse>
get() = _initVerificationData
private val _aadharVerificationStatusResponse = MutableLiveData<UploadDataAsyncResponse>()
val aadharVerificationStatusResponse: LiveData<UploadDataAsyncResponse>
get() = _aadharVerificationStatusResponse
private val _dataAsyncResponse = MutableLiveData<UploadDataAsyncResponse>()
val dataAsyncResponse: LiveData<UploadDataAsyncResponse>
get() = _dataAsyncResponse
fun submitSelfie(bytes: ByteArray) {
val requestBody = getMultipartRequestBody(SELFIE_IMAGE)
val multipartBody = getMultipartBody(bytes, FILE_NAME)
@@ -71,10 +82,13 @@ class KycVM : BaseVM() {
fun submitKycDetails(lineOne: String?, fatherName: String?, motherName: String?) {
coroutineScope.launch {
val address = Address(lineOne = lineOne, document_temp_url = PreferenceManager.getStringPreference(
KYC_DOCUMENT_UPLOAD_URL))
val address = Address(
lineOne = lineOne, document_temp_url = PreferenceManager.getStringPreference(
KYC_DOCUMENT_UPLOAD_URL
)
)
val parentDetails = ParentDetails(fatherName = fatherName, motherName = motherName)
val kycRequest = KycRequest(address = address, parentDetails = parentDetails )
val kycRequest = KycRequest(address = address, parentDetails = parentDetails)
val response = repository.updateKycDetails(kycRequest)
if (response.error == null) {
_kycDetailsSubmitAsyncData.value = response.data
@@ -106,11 +120,34 @@ class KycVM : BaseVM() {
when (type) {
SELFIE -> _selfieUploadAsyncData.value = response.data
UPDATE_KYC_DETAILS -> _kycDetailsSubmitAsyncData.value = response.data
AADHAR_VERIFICATION-> _dataAsyncResponse.value = response.data
}
}
}
}
fun initVerification() {
coroutineScope.launch {
val response = repository.initVerification()
if (response.error == null) {
val initVerificationData = response.data
if (initVerificationData?.aadharIdentifier.isNullOrBlank())
initVerificationData?.aadharIdentifier = UserManager.getPhoneNumber()
_initVerificationData.value = initVerificationData
}
}
}
fun fetchAadharVerificationStatusData(data: AadharVerificationStatusData) {
coroutineScope.launch {
val response = repository.fetchAadharVerificationStatus(data)
if (response.error == null) {
_aadharVerificationStatusResponse.value = response.data
}
}
}
companion object {
private const val KYC = "kyc"
private const val KYC_FILE_NAME = "kyc.jpg"

View File

@@ -0,0 +1,30 @@
/*
* *
* * Copyright (c) 2020 . All rights reserved @Navi
*
*/
package com.navi.kyc.adharverification.digio
import `in`.digio.sdk.kyc.DigioEnvironment
import `in`.digio.sdk.kyc.DigioKycConfig
import `in`.digio.sdk.kyc.DigioSession
import android.app.Activity
class AdharVerificationHelper {
fun initConfig(activity: Activity, requestId: String, identifier: String) {
init(activity, requestId, identifier)
}
private fun init(activity: Activity, requestId: String, identifier: String) {
try {
val config = DigioKycConfig()
config.environment = DigioEnvironment.PRODUCTION
val session = DigioSession()
session.init(activity, config)
session.startSession(requestId, identifier)
} catch (e: Exception) {
}
}
}

View File

@@ -7,6 +7,8 @@
package com.navi.network.retrofit
import com.navi.getloan.bankdetails.models.Bank
import com.navi.getloan.kyc.models.AadharVerificationStatusData
import com.navi.getloan.kyc.models.InitVerificationResponse
import com.navi.models.ApplicationSummary
import com.navi.models.LoanSummary
import com.navi.models.Offer
@@ -298,4 +300,14 @@ interface RetrofitService {
@GET("/fetch-bank-details")
suspend fun fetchAllBanks(
): Response<GenericResponse<List<Bank>>>
//adhaar verification
@GET("/customer-service/customers/me/kyc/aadhar/initiate-verification")
suspend fun initiateAdharVerification(
): Response<GenericResponse<InitVerificationResponse>>
@POST("/customer-service/customers/me/kyc/aadhar/verification-status")
suspend fun fetchVerificationStatus(
@Body body: AadharVerificationStatusData
): Response<GenericResponse<UploadDataAsyncResponse>>
}

View File

@@ -0,0 +1,2 @@
configurations.maybeCreate("default")
artifacts.add("default", file('digio-kyc-1.0.0.aar'))

Binary file not shown.

View File

@@ -1,2 +1,2 @@
include ':app'
include ':app', ':digio-kyc-1.0.0'
rootProject.name='android-customer-app'