Commit b3864407 authored by yinjiacheng's avatar yinjiacheng

add 人脸验证UI

parent 7a19c715
......@@ -3,7 +3,8 @@ package com.yidian.shenghuoquan.newscontent.ui.auth
import com.yidian.shenghuoquan.newscontent.bean.LifeAccountMerchantAuthData
import com.yidian.shenghuoquan.newscontent.bean.LifeAccountPersonalAuthData
import com.yidian.shenghuoquan.newscontent.constant.Constant
import com.yidian.shenghuoquan.newscontent.http.httpbean.*
import com.yidian.shenghuoquan.newscontent.http.httpbean.BusinessLicenseOCRBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.GetIDCardOCRBean
/**
* author: yinjiacheng
......@@ -38,8 +39,10 @@ object LifeAccountAuthDataManager {
val requestMap = HashMap<String, String?>()
requestMap["front_img"] = personalAuthData.idCardPortraitFaceObjectKey
requestMap["bak_img"] = personalAuthData.idCardNationalEmblemFaceObjectKey
requestMap["front_completeness"] = personalAuthData.idCardPortraitFaceCompleteness.toString()
requestMap["bak_completeness"] = personalAuthData.idCardNationalEmblemFaceCompleteness.toString()
requestMap["front_completeness"] =
personalAuthData.idCardPortraitFaceCompleteness.toString()
requestMap["bak_completeness"] =
personalAuthData.idCardNationalEmblemFaceCompleteness.toString()
requestMap["id_card"] = personalAuthData.idCardNum
requestMap["gender"] = personalAuthData.gender
requestMap["name"] = personalAuthData.realName
......@@ -77,9 +80,9 @@ object LifeAccountAuthDataManager {
* 生成营业执照上传接口请求体
*/
fun generateAuthBusinessLicenseCommitRequest(
userId: Long,
dataType: Int,
lifeAccountId: Long?
userId: Long,
dataType: Int,
lifeAccountId: Long?
): HashMap<String, String?> {
val requestMap = HashMap<String, String?>()
requestMap["user_id"] = userId.toString()
......@@ -112,15 +115,17 @@ object LifeAccountAuthDataManager {
* 生成个体工商户身份上传接口请求体
*/
fun generateAuthIndividualBusinessIdentityCommitRequest(
dataType: Int
dataType: Int
): HashMap<String, String?> {
val requestMap = HashMap<String, String?>()
requestMap["code"] = merchantAuthData.registrationCode
requestMap["data_type"] = dataType.toString()
requestMap["front_img"] = personalAuthData.idCardPortraitFaceObjectKey
requestMap["bak_img"] = personalAuthData.idCardNationalEmblemFaceObjectKey
requestMap["front_completeness"] = personalAuthData.idCardPortraitFaceCompleteness.toString()
requestMap["bak_completeness"] = personalAuthData.idCardNationalEmblemFaceCompleteness.toString()
requestMap["front_completeness"] =
personalAuthData.idCardPortraitFaceCompleteness.toString()
requestMap["bak_completeness"] =
personalAuthData.idCardNationalEmblemFaceCompleteness.toString()
requestMap["idcard_number"] = personalAuthData.idCardNum
requestMap["gender"] = personalAuthData.gender
requestMap["name"] = personalAuthData.realName
......@@ -139,15 +144,17 @@ object LifeAccountAuthDataManager {
* 生成普通企业法人身份信息上传接口请求体
*/
fun generateAuthEnterpriseLegalIdentityCommitRequest(
authRecordId: Long,
lifeAccountId: Long?
authRecordId: Long,
lifeAccountId: Long?
): HashMap<String, String?> {
val requestMap = HashMap<String, String?>()
requestMap["record_id"] = authRecordId.toString()
requestMap["front_img"] = personalAuthData.idCardPortraitFaceObjectKey
requestMap["bak_img"] = personalAuthData.idCardNationalEmblemFaceObjectKey
requestMap["front_completeness"] = personalAuthData.idCardPortraitFaceCompleteness.toString()
requestMap["bak_completeness"] = personalAuthData.idCardNationalEmblemFaceCompleteness.toString()
requestMap["front_completeness"] =
personalAuthData.idCardPortraitFaceCompleteness.toString()
requestMap["bak_completeness"] =
personalAuthData.idCardNationalEmblemFaceCompleteness.toString()
requestMap["idcard_number"] = personalAuthData.idCardNum
requestMap["gender"] = personalAuthData.gender
requestMap["name"] = personalAuthData.realName
......
......@@ -4,7 +4,6 @@ import android.app.Activity
import android.content.ContentResolver
import android.content.Intent
import android.graphics.BitmapFactory
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Bundle
......@@ -42,6 +41,7 @@ import com.yidian.shenghuoquan.newscontent.utils.FileUtil
import com.yidian.shenghuoquan.newscontent.utils.KS3Core
import com.yidian.shenghuoquan.newscontent.widget.LifeAccountAuthIdentityInfoEditView
import com.yidian.shenghuoquan.newscontent.widget.LifeAccountAuthImageView
import com.yidian.shenghuoquan.newscontent.widget.LifeAccountFaceAuthView
import com.yidian.utils.ToastUtil
import java.io.File
import java.io.FileOutputStream
......@@ -57,7 +57,8 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
DetectCallback, KS3Core.OnKS3TaskListener, IAuthPersonalCheckCallback,
IAuthLiveIdentityCallback, LifeAccountAuthImageView.OnLifeAccountAuthImageViewCallback,
LifeAccountAuthIdentityInfoEditView.OnLifeAccountAuthIdentityInfoEditViewCallback,
IAuthIndividualBusinessIdentityCommitCallback, IAuthEnterpriseLiveIdentityCallback {
IAuthIndividualBusinessIdentityCommitCallback, IAuthEnterpriseLiveIdentityCallback,
LifeAccountFaceAuthView.OnLifeAccountFaceAuthCallback {
companion object {
// 身份证采集页面回传数据
......@@ -96,7 +97,7 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
/**
* 当前认证类型
*/
private var authType: Int? = 0
private var authType: Int? = null
override fun createViewBinding(
inflater: LayoutInflater,
......@@ -121,7 +122,7 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
}
private fun initView() {
authType = arguments?.getInt(Constant.TYPE_AUTH, 0)
authType = arguments?.getInt(Constant.TYPE_AUTH, -1) ?: Constant.TYPE_AUTH_PERSONAL
when (authType) {
Constant.TYPE_AUTH_PERSONAL -> {
viewBinding.evRealName.setTitleContent(resources.getString(R.string.real_name))
......@@ -134,18 +135,19 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
}
}
viewBinding.evMobile.isVisible = authType == Constant.TYPE_AUTH_COMMON_ENTERPRISE
viewBinding.clFaceAuth.isVisible = authType == Constant.TYPE_AUTH_INDIVIDUAL_BUSINESS
viewBinding.avFaceAuth.isVisible =
(authType == Constant.TYPE_AUTH_PERSONAL) or (authType == Constant.TYPE_AUTH_INDIVIDUAL_BUSINESS)
}
private fun initListener() {
viewBinding.ivIdCardPortraitFace.setOnClickListener(this)
viewBinding.ivIdCardNationalEmblemFace.setOnClickListener(this)
viewBinding.ivFaceAuthStart.setOnClickListener(this)
viewBinding.ivIdCardPortraitFace.setOnLifeAccountAuthImageViewCallback(this)
viewBinding.ivIdCardNationalEmblemFace.setOnLifeAccountAuthImageViewCallback(this)
viewBinding.evRealName.setOnLifeAccountAuthIdentityInfoEditViewCallback(this)
viewBinding.evIdCardNumber.setOnLifeAccountAuthIdentityInfoEditViewCallback(this)
viewBinding.evMobile.setOnLifeAccountAuthIdentityInfoEditViewCallback(this)
viewBinding.avFaceAuth.setOnLifeAccountFaceAuthCallback(this)
}
/**
......@@ -224,26 +226,6 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
).show()
}
}
R.id.iv_face_auth_start -> {
// 判断是否满足条件进行活体检测
if (!checkFaceAuthCondition()) return
when (authType) {
Constant.TYPE_AUTH_PERSONAL -> {
ApiService.authPersonalCheck(
this,
LifeAccountAuthDataManager.generateAuthPersonalCheckRequest()
)
}
Constant.TYPE_AUTH_INDIVIDUAL_BUSINESS -> {
ApiService.authIndividualBusinessIdentityCommit(
this,
LifeAccountAuthDataManager.generateAuthIndividualBusinessIdentityCommitRequest(
Constant.TYPE_INDIVIDUAL_BUSINESS
)
)
}
}
}
}
}
......@@ -452,9 +434,12 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
*/
private fun startIDCardOCR() {
val requestParams = HashMap<String, String?>()
requestParams["posit_image_objectid"] = LifeAccountAuthDataManager.personalAuthData.idCardPortraitFaceObjectKey
requestParams["back_image_objectid"] = LifeAccountAuthDataManager.personalAuthData.idCardNationalEmblemFaceObjectKey
requestParams["bucket"] = LifeAccountAuthDataManager.personalAuthData.idCardPortraitFaceBucket
requestParams["posit_image_objectid"] =
LifeAccountAuthDataManager.personalAuthData.idCardPortraitFaceObjectKey
requestParams["back_image_objectid"] =
LifeAccountAuthDataManager.personalAuthData.idCardNationalEmblemFaceObjectKey
requestParams["bucket"] =
LifeAccountAuthDataManager.personalAuthData.idCardPortraitFaceBucket
ApiService.getIDCardOCR(this, requestParams)
}
......@@ -495,7 +480,7 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
// 保存人脸验证结果
LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass = true
// 人脸验证通过UI
changeFaceAuthUI(true)
viewBinding.avFaceAuth.showFaceAuthResult(true)
// 删除活体检测数据
File(cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA).delete()
// 锁定当前输入状态 即完成人脸验证后无法修改身份证照片、姓名、身份证号
......@@ -523,7 +508,7 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
Log.e(Constant.LIFE_ACCOUNT_AUTH_TAG, "live detect failure, message: ${t?.reason}")
LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass = false
// 人脸验证未通过UI
changeFaceAuthUI(false)
viewBinding.avFaceAuth.showFaceAuthResult(false)
}
override fun onPreStart() {
......@@ -564,7 +549,7 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
Constant.LIFE_ACCOUNT_AUTH_TAG,
"alive detect detect failure, errorCode: $errorCode, errorMessage: $errorMessage"
)
changeFaceAuthUI(false)
viewBinding.avFaceAuth.showFaceAuthResult(false)
}
}
......@@ -590,7 +575,8 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
}
val requestParams = HashMap<String, String?>()
requestParams["biz_token"] = LifeAccountAuthDataManager.personalAuthData.liveDetectBizToken
requestParams["meglive_objectid"] = LifeAccountAuthDataManager.personalAuthData.liveDetectObjectKey
requestParams["meglive_objectid"] =
LifeAccountAuthDataManager.personalAuthData.liveDetectObjectKey
ApiService.identifyIdOcrVerify(this, requestParams)
}
......@@ -684,6 +670,27 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
}
}
override fun onStartFaceAuth() {
// 判断是否满足条件进行活体检测
if (!checkFaceAuthCondition()) return
when (authType) {
Constant.TYPE_AUTH_PERSONAL -> {
ApiService.authPersonalCheck(
this,
LifeAccountAuthDataManager.generateAuthPersonalCheckRequest()
)
}
Constant.TYPE_AUTH_INDIVIDUAL_BUSINESS -> {
ApiService.authIndividualBusinessIdentityCommit(
this,
LifeAccountAuthDataManager.generateAuthIndividualBusinessIdentityCommitRequest(
Constant.TYPE_INDIVIDUAL_BUSINESS
)
)
}
}
}
override fun authIndividualBusinessIdentityCommitSuccess() {
// 身份信息校验成功后才允许进行人脸验证
// 若存在上一次活体检测数据则删除 处理活体检测失败 再次进入
......@@ -714,24 +721,6 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
)
}
/**
* 人脸验证结果UI
* @param result true为验证通过 false为验证未通过
*/
private fun changeFaceAuthUI(result: Boolean) {
if (result) {
viewBinding.tvFaceAuthResult.text = resources.getText(R.string.face_auth_success)
viewBinding.tvFaceAuthResult.setTextColor(Color.parseColor("#FF6BB81F"))
viewBinding.ivFaceAuthStart.visibility = View.GONE
viewBinding.tvFaceAuthErrorTips.visibility = View.GONE
} else {
viewBinding.tvFaceAuthResult.text = resources.getText(R.string.face_auth_fail)
viewBinding.tvFaceAuthResult.setTextColor(Color.parseColor("#FFFF3A3A"))
viewBinding.tvFaceAuthErrorTips.visibility = View.VISIBLE
viewBinding.tvFaceAuthErrorTips.text = resources.getText(R.string.face_auth_error_tips)
}
}
/**
* 本地校验是否可以进行人脸验证
* 必须同时满足真实姓名已填、身份证号已填、身份证两面已上传、职业标签已选
......
package com.yidian.shenghuoquan.newscontent.widget
import android.content.Context
import android.graphics.Color
import android.util.AttributeSet
import android.view.View
import com.yidian.nightmode.widget.YdConstraintLayout
import com.yidian.shenghuoquan.newscontent.R
import com.yidian.shenghuoquan.newscontent.databinding.ViewLifeAccountFaceAuthBinding
/**
* author: yinjiacheng
* date: 6/6/21 3:57 PM
* description: 生活号认证 人脸认证
*/
class LifeAccountFaceAuthView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
) : YdConstraintLayout(context, attrs, defStyle), View.OnClickListener {
private val viewBinding = ViewLifeAccountFaceAuthBinding.bind(
View.inflate(
getContext(), R.layout.view_life_account_face_auth, this
)
)
private var callback: OnLifeAccountFaceAuthCallback? = null
init {
viewBinding.ivFaceAuthStart.setOnClickListener(this)
}
/**
* 人脸验证结果UI
* @param result true为验证通过 false为验证未通过
*/
fun showFaceAuthResult(result: Boolean) {
if (result) {
viewBinding.tvFaceAuthResult.text = resources.getText(R.string.face_auth_success)
viewBinding.tvFaceAuthResult.setTextColor(Color.parseColor("#FF6BB81F"))
viewBinding.ivFaceAuthStart.visibility = View.GONE
viewBinding.tvFaceAuthErrorTips.visibility = View.GONE
} else {
viewBinding.tvFaceAuthResult.text = resources.getText(R.string.face_auth_fail)
viewBinding.tvFaceAuthResult.setTextColor(Color.parseColor("#FFFF3A3A"))
viewBinding.tvFaceAuthErrorTips.visibility = View.VISIBLE
viewBinding.tvFaceAuthErrorTips.text = resources.getText(R.string.face_auth_error_tips)
}
}
override fun onClick(v: View?) {
if (v?.id == R.id.iv_face_auth_start) {
callback?.onStartFaceAuth()
}
}
fun setOnLifeAccountFaceAuthCallback(callback: OnLifeAccountFaceAuthCallback) {
this.callback = callback
}
interface OnLifeAccountFaceAuthCallback {
/**
* 进行人脸验证
*/
fun onStartFaceAuth()
}
}
\ No newline at end of file
......@@ -88,65 +88,13 @@
app:LifeAccountAuthIdentityInfoEditView_hint_text="@string/input_id_card_number"
app:layout_constraintTop_toBottomOf="@id/ev_id_card_number" />
<com.yidian.nightmode.widget.YdConstraintLayout
android:id="@+id/cl_face_auth"
<com.yidian.shenghuoquan.newscontent.widget.LifeAccountFaceAuthView
android:id="@+id/av_face_auth"
android:layout_width="match_parent"
android:layout_height="85dp"
android:layout_height="wrap_content"
android:paddingStart="19dp"
android:paddingTop="17dp"
android:paddingEnd="12dp"
android:paddingBottom="6dp"
android:visibility="gone"
app:layout_constraintTop_toBottomOf="@id/ev_id_card_number">
<com.yidian.nightmode.widget.YdTextView
android:id="@+id/tv_face_auth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:text="@string/face_auth"
android:textColor="#FF333333"
android:textSize="15sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.yidian.nightmode.widget.YdTextView
android:id="@+id/tv_face_auth_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="2dp"
android:includeFontPadding="false"
android:text="@string/start_face_auth"
android:textColor="#FF1852F1"
android:textSize="15sp"
app:layout_constraintEnd_toStartOf="@id/iv_face_auth_start"
app:layout_constraintTop_toTopOf="parent" />
<com.yidian.nightmode.widget.YdImageView
android:id="@+id/iv_face_auth_start"
android:layout_width="23dp"
android:layout_height="23dp"
android:src="@mipmap/icon_next"
app:layout_constraintBottom_toBottomOf="@id/tv_face_auth"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_face_auth" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="17dp"
android:background="#FFF2F2F2"
app:layout_constraintTop_toBottomOf="@id/tv_face_auth" />
<com.yidian.nightmode.widget.YdTextView
android:id="@+id/tv_face_auth_error_tips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:textColor="#FFFF3A3A"
android:textSize="12sp"
app:layout_constraintBottom_toBottomOf="parent" />
</com.yidian.nightmode.widget.YdConstraintLayout>
app:layout_constraintTop_toBottomOf="@id/ev_id_card_number" />
</com.yidian.nightmode.widget.YdConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<com.yidian.nightmode.widget.YdConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="17dp"
android:paddingBottom="6dp">
<com.yidian.nightmode.widget.YdTextView
android:id="@+id/tv_face_auth"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:includeFontPadding="false"
android:text="@string/face_auth"
android:textColor="#FF333333"
android:textSize="15sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.yidian.nightmode.widget.YdTextView
android:id="@+id/tv_face_auth_result"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="2dp"
android:includeFontPadding="false"
android:text="@string/start_face_auth"
android:textColor="#FF1852F1"
android:textSize="15sp"
app:layout_constraintEnd_toStartOf="@id/iv_face_auth_start"
app:layout_constraintTop_toTopOf="parent" />
<com.yidian.nightmode.widget.YdImageView
android:id="@+id/iv_face_auth_start"
android:layout_width="23dp"
android:layout_height="23dp"
android:src="@mipmap/icon_next"
app:layout_constraintBottom_toBottomOf="@id/tv_face_auth"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_face_auth" />
<View
android:id="@+id/view_divider"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginTop="17dp"
android:background="#FFF2F2F2"
app:layout_constraintTop_toBottomOf="@id/tv_face_auth" />
<com.yidian.nightmode.widget.YdTextView
android:id="@+id/tv_face_auth_error_tips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:includeFontPadding="false"
android:textColor="#FFFF3A3A"
android:textSize="12sp"
app:layout_constraintTop_toBottomOf="@id/view_divider" />
</com.yidian.nightmode.widget.YdConstraintLayout>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment