Commit 735797d8 authored by yinjiacheng's avatar yinjiacheng

update 个人认证切换XInsight API

parent 609bd226
package com.yidian.shenghuoquan.newscontent.ui.auth
import com.yidian.framework.mobile.insight.identity.IdentityCardResult
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.AuthAuthenticationBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthMerchantCheckBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.BusinessLicenseOCRBean
/**
* author: yinjiacheng
* date: 7/15/21 5:32 PM
* description: 生活号认证数据管理 接入XInsight
*/
object LifeAccountAuthDataManagerV2 {
val personalAuthData by lazy { LifeAccountPersonalAuthData() }
val merchantAuthData by lazy { LifeAccountMerchantAuthData() }
/**
* 将身份证人像面OCR结果填入
*/
fun generateIDCardPortraitFaceData(data: IdentityCardResult) {
personalAuthData.idCardPortraitFaceCompleteness = data.posit.completeness
personalAuthData.idCardNum = data.posit.idcard_number
personalAuthData.gender = data.posit.gender
personalAuthData.realName = data.posit.name
personalAuthData.address = data.posit.address
personalAuthData.nationality = data.posit.nationality
}
/**
* 将身份证国徽面OCR结果填入
*/
fun generateIDCardNationEmblemFaceData(data: IdentityCardResult) {
personalAuthData.idCardNationalEmblemFaceCompleteness = data.back.completeness
personalAuthData.validDateStart = data.back.valid_date_start
personalAuthData.validDateEnd = data.back.valid_date_end
personalAuthData.issuedBy = data.back.issued_by
}
/**
* 填入个人认证流程回显数据
* 身份证两面完整度此时一定是0
*/
fun generatePersonalAuthData(data: AuthAuthenticationBean.Response) {
personalAuthData.isFaceAuthPass = data.live_identity_status == Constant.ALIVE_DETECT_SUCCESS
personalAuthData.realName = data.full_name
personalAuthData.idCardNum = data.id_card
personalAuthData.occupation = data.occupation
personalAuthData.idCardPortraitFaceUrl = data.posit_image_url
personalAuthData.idCardNationalEmblemFaceUrl = data.back_image_url
personalAuthData.address = data.address
personalAuthData.nationality = data.nationality
personalAuthData.gender = data.gender
personalAuthData.validDateStart = data.validity_start_time
personalAuthData.validDateEnd = data.validity_end_time
personalAuthData.issuedBy = data.issued_by
personalAuthData.isIDCardPortraitFaceUpload = true
personalAuthData.isIDCardNationalEmblemFaceUpload = true
personalAuthData.idCardPortraitFaceCompleteness = 0
personalAuthData.idCardNationalEmblemFaceCompleteness = 0
}
/**
* 生成身份信息校验接口请求体
*/
fun generateAuthPersonalCheckRequest(): HashMap<String, String?> {
val requestMap = HashMap<String, String?>()
requestMap["posit_image_url"] = personalAuthData.idCardPortraitFaceUrl
requestMap["back_image_url"] = personalAuthData.idCardNationalEmblemFaceUrl
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
requestMap["occupation"] = personalAuthData.occupation
requestMap["address"] = personalAuthData.address
requestMap["nationality"] = personalAuthData.nationality
requestMap["valid_date_start"] = personalAuthData.validDateStart
requestMap["valid_date_end"] = personalAuthData.validDateEnd
requestMap["issued_by"] = personalAuthData.issuedBy
return requestMap
}
/**
* 将营业执照OCR结果填入
*/
fun generateMerchantAuthData(data: BusinessLicenseOCRBean.Response) {
merchantAuthData.registrationName = data.name
merchantAuthData.registrationCode = data.code
merchantAuthData.type = data.type
merchantAuthData.addr = data.addr
merchantAuthData.pers = data.pers
merchantAuthData.scope = data.scope
merchantAuthData.time = data.time
merchantAuthData.regi = data.regi
merchantAuthData.organizer = data.organizer
merchantAuthData.date = data.date
merchantAuthData.comp = data.comp
merchantAuthData.num = data.num
merchantAuthData.form = data.form
merchantAuthData.funding = data.funding
merchantAuthData.dateIssue = data.date_issue
}
/**
* 填入企业认证回显数据
* 身份证两面完整度此时一定是0
*/
fun generateMerchantAuthData(data: AuthMerchantCheckBean.Response) {
merchantAuthData.authRecordId = data.enterprise_auth_record_id
merchantAuthData.registrationName = data.name
merchantAuthData.registrationCode = data.code
merchantAuthData.merchantType = data.data_type
merchantAuthData.isBusinessLicenseUpload = true
merchantAuthData.type = data.enterprice_type
merchantAuthData.addr = data.enterprice_address
merchantAuthData.scope = data.businesss_scope
merchantAuthData.time = data.term_time
merchantAuthData.regi = data.registered_capital
merchantAuthData.organizer = data.organizer
merchantAuthData.date = data.establishment_date
merchantAuthData.comp = data.registration_authority
merchantAuthData.num = data.num
merchantAuthData.form = data.form
merchantAuthData.funding = data.funding
merchantAuthData.dateIssue = data.issue_date
merchantAuthData.businessLicenseUrl = data.business_image_url
merchantAuthData.pers = data.pers
personalAuthData.realName = data.legal_person
personalAuthData.idCardNum = data.legal_id_card
personalAuthData.phoneNum = data.mobile
personalAuthData.isFaceAuthPass = data.live_identity_status == Constant.ALIVE_DETECT_SUCCESS
personalAuthData.address = data.legal_address
personalAuthData.nationality = data.legal_nationality
personalAuthData.issuedBy = data.legal_issued_by
personalAuthData.validDateStart = data.legal_validity_start_time
personalAuthData.validDateEnd = data.legal_validity_end_time
personalAuthData.idCardPortraitFaceUrl = data.posit_image_url
personalAuthData.idCardNationalEmblemFaceUrl = data.back_image_url
personalAuthData.isIDCardPortraitFaceUpload = true
personalAuthData.isIDCardNationalEmblemFaceUpload = true
personalAuthData.idCardPortraitFaceCompleteness = 0
personalAuthData.idCardNationalEmblemFaceCompleteness = 0
}
/**
* 生成营业执照上传接口请求体
*/
fun generateAuthBusinessLicenseCommitRequest(
lifeAccountId: String?, recordId: Long?
): HashMap<String, String?> {
val requestMap = HashMap<String, String?>()
requestMap["code"] = merchantAuthData.registrationCode
requestMap["name"] = merchantAuthData.registrationName
requestMap["type"] = merchantAuthData.type
requestMap["addr"] = merchantAuthData.addr
requestMap["pers"] = merchantAuthData.pers
requestMap["scope"] = merchantAuthData.scope
requestMap["time"] = merchantAuthData.time
requestMap["regi"] = merchantAuthData.regi
requestMap["organizer"] = merchantAuthData.organizer
requestMap["date"] = merchantAuthData.date
requestMap["comp"] = merchantAuthData.comp
requestMap["num"] = merchantAuthData.num
requestMap["form"] = merchantAuthData.form
requestMap["funding"] = merchantAuthData.funding
requestMap["issue_date"] = merchantAuthData.dateIssue
requestMap["entterprise_image_url"] = merchantAuthData.businessLicenseUrl
requestMap["data_from"] = Constant.DATA_FROM_B.toString()
requestMap["data_type"] = merchantAuthData.merchantType.toString()
lifeAccountId?.let { requestMap["life_account_id"] = it }
recordId?.let { requestMap["enterprise_auth_record_id"] = it.toString() }
return requestMap
}
/**
* 生成个体工商户身份上传接口请求体
*/
fun generateAuthIndividualBusinessIdentityCommitRequest(): HashMap<String, String?> {
val requestMap = HashMap<String, String?>()
requestMap["record_id"] = merchantAuthData.authRecordId.toString()
requestMap["posit_image_url"] = personalAuthData.idCardPortraitFaceUrl
requestMap["back_image_url"] = personalAuthData.idCardNationalEmblemFaceUrl
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
requestMap["address"] = personalAuthData.address
requestMap["nationality"] = personalAuthData.nationality
requestMap["valid_date_start"] = personalAuthData.validDateStart
requestMap["valid_date_end"] = personalAuthData.validDateEnd
requestMap["issued_by"] = personalAuthData.issuedBy
return requestMap
}
/**
* 生成普通企业法人身份信息上传接口请求体
*/
fun generateAuthEnterpriseLegalIdentityCommitRequest(
lifeAccountId: String?
): HashMap<String, String?> {
val requestMap = HashMap<String, String?>()
requestMap["record_id"] = merchantAuthData.authRecordId.toString()
requestMap["posit_image_url"] = personalAuthData.idCardPortraitFaceUrl
requestMap["back_image_url"] = personalAuthData.idCardNationalEmblemFaceUrl
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
requestMap["address"] = personalAuthData.address
requestMap["nationality"] = personalAuthData.nationality
requestMap["valid_date_start"] = personalAuthData.validDateStart
requestMap["valid_date_end"] = personalAuthData.validDateEnd
requestMap["issued_by"] = personalAuthData.issuedBy
requestMap["mobile"] = personalAuthData.phoneNum
lifeAccountId?.let { requestMap["life_account_id"] = it }
return requestMap
}
/**
* 生成个体工商户认证完成接口请求体
*/
fun generateAuthIndividualBusinessCompleteRequest(lifeAccountId: String?): HashMap<String, String?> {
val requestMap = HashMap<String, String?>()
requestMap["record_id"] = merchantAuthData.authRecordId.toString()
lifeAccountId?.let { requestMap["life_account_id"] = it }
return requestMap
}
}
package com.yidian.shenghuoquan.newscontent.ui.auth
import android.Manifest
import android.app.Activity
import android.content.Intent
import android.graphics.BitmapFactory
import android.os.Bundle
import android.provider.MediaStore
import android.text.InputFilter
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import com.tbruyelle.rxpermissions3.RxPermissions
import com.yidian.common.base.BaseFragment
import com.yidian.framework.mobile.insight.config.IdentityCardType
import com.yidian.framework.mobile.insight.config.ScreenOrientation
import com.yidian.framework.mobile.insight.faceid.LiveVerifyCallBack
import com.yidian.framework.mobile.insight.faceid.bean.LiveVerityResult
import com.yidian.framework.mobile.insight.identity.IdentityCardResult
import com.yidian.framework.mobile.insight.identity.IdentityCardVerifyCallBack
import com.yidian.framework.mobile.insight.manage.XInsight
import com.yidian.shenghuoquan.newscontent.R
import com.yidian.shenghuoquan.newscontent.adapter.BottomSelectAdapter
import com.yidian.shenghuoquan.newscontent.bean.BottomSelectBean
import com.yidian.shenghuoquan.newscontent.bean.HintOptionBean
import com.yidian.shenghuoquan.newscontent.constant.Constant
import com.yidian.shenghuoquan.newscontent.databinding.FragmentLifeAccountIdCardAuthBinding
import com.yidian.shenghuoquan.newscontent.http.ApiService
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthEnterpriseLiveIdentityCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthIndividualBusinessIdentityCommitCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthLiveIdentityCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthPersonalCheckCallback
import com.yidian.shenghuoquan.newscontent.http.httpbean.*
import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog
import com.yidian.shenghuoquan.newscontent.ui.dialog.HintDialog
import com.yidian.shenghuoquan.newscontent.utils.BitmapUtil
import com.yidian.shenghuoquan.newscontent.utils.FileUtil
import com.yidian.shenghuoquan.newscontent.utils.InputFilterUtil
import com.yidian.shenghuoquan.newscontent.widget.LifeAccountAuthIdentityInfoEditView
import com.yidian.shenghuoquan.newscontent.widget.LifeAccountAuthImageView
import com.yidian.shenghuoquan.newscontent.widget.LifeAccountFaceAuthView
import com.yidian.shenghuoquan.newscontent.widget.PrivacyAgreementView
import com.yidian.utils.ToastUtil
import java.io.File
/**
* author: yinjiacheng
* date: 7/15/21 5:32 PM
* description: 生活号身份证认证 接入XInsight
*/
// TODO: 7/15/21 活体检测临时数据删除
// TODO: 7/15/21 接入Luban压缩
class LifeAccountIDCardAuthFragmentV2 : BaseFragment<FragmentLifeAccountIdCardAuthBinding>(), View.OnClickListener,
BottomSelectAdapter.OnItemClickListener<BottomSelectBean>, IAuthPersonalCheckCallback, IAuthLiveIdentityCallback,
LifeAccountAuthImageView.OnLifeAccountAuthImageViewCallback,
LifeAccountAuthIdentityInfoEditView.OnLifeAccountAuthIdentityInfoEditViewCallback, IAuthIndividualBusinessIdentityCommitCallback,
IAuthEnterpriseLiveIdentityCallback, LifeAccountFaceAuthView.OnLifeAccountFaceAuthCallback,
PrivacyAgreementView.OnPrivacyAgreementCallback, LiveVerifyCallBack {
companion object {
// 身份证采集页面回传数据
private const val EXTRA_NAME_ID_CARD_IMAGE = "idcardimg_bitmap"
// 认证数据
const val EXTRA_AUTH_DATA = "authData"
}
/**
* 标识用户当前上传的是身份证人像面或身份证国徽面 帮助onActivityResult区分
*/
private var curFace: Int = -1
/**
* sdcard/Android/data/package/cache
*/
private val cachePath by lazy { activity?.externalCacheDir?.absolutePath }
/**
* 当前认证类型
*/
private var authType: Int? = null
override fun createViewBinding(
inflater: LayoutInflater,
container: ViewGroup?
): FragmentLifeAccountIdCardAuthBinding {
return FragmentLifeAccountIdCardAuthBinding.inflate(layoutInflater, container, false)
}
override fun onHiddenChanged(hidden: Boolean) {
super.onHiddenChanged(hidden)
if (!hidden) {
// fragment显示
initView()
}
}
override fun init(savedInstanceState: Bundle?) {
super.init(savedInstanceState)
initView()
initListener()
initData()
}
private fun initView() {
authType = arguments?.getInt(Constant.TYPE_AUTH, Constant.TYPE_AUTH_PERSONAL)
?: Constant.TYPE_AUTH_PERSONAL
when (authType) {
Constant.TYPE_AUTH_PERSONAL -> {
viewBinding.evRealName.setTitleContent(resources.getString(R.string.real_name))
}
Constant.TYPE_AUTH_INDIVIDUAL_BUSINESS -> {
viewBinding.evRealName.setTitleContent(resources.getString(R.string.individual_business_manager_name))
}
Constant.TYPE_AUTH_COMMON_ENTERPRISE -> {
viewBinding.evRealName.setTitleContent(resources.getString(R.string.enterprise_legal_name))
}
}
viewBinding.evMobile.isVisible = authType == Constant.TYPE_AUTH_COMMON_ENTERPRISE
viewBinding.avFaceAuth.isVisible =
(authType == Constant.TYPE_AUTH_PERSONAL) or (authType == Constant.TYPE_AUTH_INDIVIDUAL_BUSINESS)
// 输入过滤
viewBinding.evRealName.setInputFilters(InputFilterUtil.getRealNameFilter(), InputFilter.LengthFilter(40))
// 身份证号码输入限制18位字符,数字+大小写x 小写x自动转大写X
viewBinding.evIdCardNumber.setInputFilters(InputFilterUtil.getIDCardNumberFilter(), InputFilter.LengthFilter(18), InputFilter.AllCaps())
viewBinding.evMobile.setInputFilters(InputFilterUtil.getPhoneNumberFilter(), InputFilter.LengthFilter(11))
}
private fun initListener() {
viewBinding.ivIdCardPortraitFace.setOnClickListener(this)
viewBinding.ivIdCardNationalEmblemFace.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)
viewBinding.avPrivacyAgreement.setOnPrivacyAgreementCallback(this)
}
private fun initData() {
// 还原认证数据
val authData = arguments?.getSerializable(EXTRA_AUTH_DATA) ?: return
if (authType == Constant.TYPE_AUTH_PERSONAL) {
fillPersonalAuthInfo(authData as AuthAuthenticationBean.Response)
} else {
fillEnterpriseAuthInfo(authData as AuthMerchantCheckBean.Response)
}
}
/**
* 个人认证流程中断,下次进入认证流程时还原进度
*/
private fun fillPersonalAuthInfo(data: AuthAuthenticationBean.Response) {
viewBinding.ivIdCardPortraitFace.addImage(data.front_id_card_url)
viewBinding.ivIdCardNationalEmblemFace.addImage(data.back_id_card_url)
viewBinding.evRealName.fillEditContent(data.full_name)
viewBinding.evIdCardNumber.fillEditContent(data.id_card)
if (data.live_identity_status == Constant.ALIVE_DETECT_SUCCESS) viewBinding.avFaceAuth.showFaceAuthResult(true)
// 如果人脸验证已通过 则直接锁定输入状态
if (data.live_identity_status == Constant.ALIVE_DETECT_SUCCESS) lockPersonalAuthInfo()
// 检查下一步条件
(activity as LifeAccountPersonalAuthActivity).checkNextCondition()
}
/**
* 企业认证流程中断,下次进入认证流程时还原进度
*/
private fun fillEnterpriseAuthInfo(data: AuthMerchantCheckBean.Response) {
viewBinding.ivIdCardPortraitFace.addImage(data.legal_front_id_card_url)
viewBinding.ivIdCardNationalEmblemFace.addImage(data.legal_back_id_card_url)
viewBinding.evRealName.fillEditContent(data.legal_person)
viewBinding.evIdCardNumber.fillEditContent(data.legal_id_card)
if (authType == Constant.TYPE_AUTH_INDIVIDUAL_BUSINESS) {
// 个体工商户
if (data.live_identity_status == Constant.ALIVE_DETECT_SUCCESS) viewBinding.avFaceAuth.showFaceAuthResult(true)
// 如果人脸验证已通过 则直接锁定输入状态
if (data.live_identity_status == Constant.ALIVE_DETECT_SUCCESS) lockEnterpriseAuthInfo()
} else {
// 普通企业
viewBinding.evMobile.fillEditContent(data.mobile)
}
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
/**
* 锁定当前输入状态
* 即完成人脸验证后无法修改身份证照片、姓名、身份证号、职业标签
*/
private fun lockPersonalAuthInfo() {
viewBinding.ivIdCardPortraitFace.disableModify()
viewBinding.ivIdCardNationalEmblemFace.disableModify()
viewBinding.evRealName.disableModify()
viewBinding.evIdCardNumber.disableModify()
if (authType == Constant.TYPE_AUTH_PERSONAL) {
(activity as LifeAccountPersonalAuthActivity).disableModifyOccupation()
}
}
/**
* 锁定当前输入状态
* 即完成人脸验证后无法修改身份证照片、姓名、身份证号
*/
private fun lockEnterpriseAuthInfo() {
viewBinding.ivIdCardPortraitFace.disableModify()
viewBinding.ivIdCardNationalEmblemFace.disableModify()
viewBinding.evRealName.disableModify()
viewBinding.evIdCardNumber.disableModify()
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.iv_id_card_portrait_face -> {
// 上传身份证人像面
curFace = Constant.ID_CARD_PORTRAIT_FACE
activity?.let {
BottomSelectDialog(
it,
this,
arrayListOf(
BottomSelectBean(Constant.ITEM_TAKE_PHOTO),
BottomSelectBean(Constant.ITEM_OPEN_ALBUM)
)
).show()
}
}
R.id.iv_id_card_national_emblem_face -> {
// 上传身份证国徽面
curFace = Constant.ID_CARD_NATIONAL_EMBLEM_FACE
activity?.let {
BottomSelectDialog(
it,
this,
arrayListOf(
BottomSelectBean(Constant.ITEM_TAKE_PHOTO),
BottomSelectBean(Constant.ITEM_OPEN_ALBUM)
)
).show()
}
}
}
}
override fun onItemClick(view: View, position: Int, data: BottomSelectBean) {
when (data.item) {
Constant.ITEM_TAKE_PHOTO -> {
// 判断camera权限
RxPermissions(this).request(Manifest.permission.CAMERA).subscribe {
if (it) {
// 调用XInsight进行身份证采集
XInsight.startIdentityCardOcr(
activity,
ScreenOrientation.VERTICAL,
if (curFace == Constant.ID_CARD_PORTRAIT_FACE) IdentityCardType.PORTRAIT else IdentityCardType.NATIONAL_EMBLEM,
Constant.REQUEST_CODE_ID_CARD_CAPTURE
)
} else {
ToastUtil.showToast(activity, "请在设置里同意相关权限")
}
}
}
Constant.ITEM_OPEN_ALBUM -> {
// 打开系统相册
startActivityForResult(
Intent(Intent.ACTION_PICK).setDataAndType(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
"image/*"
),
Constant.REQUEST_CODE_OPEN_ALBUM
)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
Constant.REQUEST_CODE_OPEN_ALBUM -> {
if (curFace == Constant.ID_CARD_PORTRAIT_FACE) {
val bitmap = BitmapUtil.generateBitmapFromUri(
activity,
data?.data,
viewBinding.ivIdCardPortraitFace
)
viewBinding.ivIdCardPortraitFace.addImage(bitmap)
FileUtil.generateFileFromUri(
activity,
data?.data,
cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE
)
BitmapUtil.compressImage(
cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE,
10
)
startIDCardVerify(Constant.ID_CARD_PORTRAIT_FACE)
} else {
val bitmap = BitmapUtil.generateBitmapFromUri(
activity,
data?.data,
viewBinding.ivIdCardNationalEmblemFace
)
viewBinding.ivIdCardNationalEmblemFace.addImage(bitmap)
FileUtil.generateFileFromUri(
activity,
data?.data,
cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE
)
BitmapUtil.compressImage(
cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE,
10
)
startIDCardVerify(Constant.ID_CARD_NATIONAL_EMBLEM_FACE)
}
}
Constant.REQUEST_CODE_ID_CARD_CAPTURE -> {
val bytes = data?.getByteArrayExtra(EXTRA_NAME_ID_CARD_IMAGE)
if (curFace == Constant.ID_CARD_PORTRAIT_FACE) {
val bitmap = bytes?.size?.let {
BitmapFactory.decodeByteArray(
bytes, 0,
it
)
}
viewBinding.ivIdCardPortraitFace.addImage(bitmap)
BitmapUtil.generateFileFromBitmap(
bitmap,
100,
cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE
)
startIDCardVerify(Constant.ID_CARD_PORTRAIT_FACE)
} else {
val bitmap = bytes?.size?.let {
BitmapFactory.decodeByteArray(
bytes, 0,
it
)
}
viewBinding.ivIdCardNationalEmblemFace.addImage(bitmap)
BitmapUtil.generateFileFromBitmap(
bitmap,
100,
cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE
)
startIDCardVerify(Constant.ID_CARD_NATIONAL_EMBLEM_FACE)
}
}
}
}
}
/**
* 执行身份证上传金山云
* @param face 身份证两面标识
*/
private fun startIDCardVerify(face: Int) {
val uploadFile = if (face == Constant.ID_CARD_PORTRAIT_FACE) {
File(cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE)
} else {
File(cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE)
}
XInsight.identityCardVerify(
if (face == Constant.ID_CARD_PORTRAIT_FACE) IdentityCardType.PORTRAIT else IdentityCardType.NATIONAL_EMBLEM,
uploadFile,
object : IdentityCardVerifyCallBack {
override fun onSucceed(identityCardResult: IdentityCardResult?, result: String?) {
if (face == Constant.ID_CARD_PORTRAIT_FACE) {
identityCardResult?.let { LifeAccountAuthDataManagerV2.generateIDCardPortraitFaceData(it) }
// 回显OCR结果
viewBinding.evRealName.fillEditContent(identityCardResult?.posit?.name)
viewBinding.evIdCardNumber.fillEditContent(identityCardResult?.posit?.idcard_number)
// 此时身份证人像面已上传并OCR识别完成 删除本地临时存储文件
File(cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE).apply {
if (exists()) delete()
}
// 检查下一步条件
if (authType == Constant.TYPE_AUTH_PERSONAL) {
activity?.let { (it as LifeAccountPersonalAuthActivity).checkNextCondition() }
} else {
activity?.let { (it as LifeAccountEnterpriseAuthActivity).checkNextCondition() }
}
} else {
identityCardResult?.let { LifeAccountAuthDataManagerV2.generateIDCardNationEmblemFaceData(it) }
// 此时身份证国徽面已上传并OCR识别完成 删除本地临时存储文件
File(cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE).apply {
if (exists()) delete()
}
// 检查下一步条件
if (authType == Constant.TYPE_AUTH_PERSONAL) {
activity?.let { (it as LifeAccountPersonalAuthActivity).checkNextCondition() }
} else {
activity?.let { (it as LifeAccountEnterpriseAuthActivity).checkNextCondition() }
}
}
}
override fun onFail(code: Int, errMsg: String?, errDomain: String?) {
}
override fun onUploadTask(positImageUrl: String?, backImageUrl: String?) {
if (face == Constant.ID_CARD_PORTRAIT_FACE) {
LifeAccountAuthDataManagerV2.personalAuthData.isIDCardPortraitFaceUpload =
true
LifeAccountAuthDataManagerV2.personalAuthData.idCardPortraitFaceUrl = positImageUrl
} else {
LifeAccountAuthDataManagerV2.personalAuthData.isIDCardNationalEmblemFaceUpload =
true
LifeAccountAuthDataManagerV2.personalAuthData.idCardNationalEmblemFaceUrl = backImageUrl
}
}
})
}
override fun authPersonCheckSuccess() {
// 身份信息校验成功后才允许进行人脸验证
XInsight.startLiveVerify(
activity,
LifeAccountAuthDataManagerV2.personalAuthData.idCardNum,
LifeAccountAuthDataManagerV2.personalAuthData.realName,
Constant.TYPE_MEG_LIVE, this
)
}
override fun authPersonCheckFailure(code: Int?, message: String?) {
if (code == Constant.ERROR_CODE_PERSONAL_AUTH_INFO_DUPLICATE) {
// 身份证号已认证并且认证手机号不是当前手机号 弹窗提示
activity?.let {
HintDialog(
it, message.toString(),
arrayListOf(
HintOptionBean(resources.getString(R.string.change)),
HintOptionBean(resources.getString(R.string.login_again))
), it as LifeAccountPersonalAuthActivity
).setRightBtnColor(ContextCompat.getColor(it, R.color.color_FF1852F1)).show()
}
return
}
// 展示输入框下错误提示
when (message) {
Constant.ERROR_MESSAGE_REAL_NAME -> {
viewBinding.evRealName.showErrorTips(
resources.getText(R.string.id_card_name_error_tips) as String
)
viewBinding.evRealName.highLightEditContent()
}
Constant.ERROR_MESSAGE_ID_CARD_NUMBER -> {
viewBinding.evIdCardNumber.showErrorTips(resources.getText(R.string.id_card_number_error_tips) as String)
viewBinding.evIdCardNumber.highLightEditContent()
}
}
}
override fun authLiveIdentitySuccess() {
}
override fun authLiveIdentityFailure(message: String?) {
}
override fun onImageClear(from: LifeAccountAuthImageView) {
if (from == viewBinding.ivIdCardPortraitFace) {
// 清除照片时删除本地文件
File(cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE).apply {
if (exists()) delete()
}
LifeAccountAuthDataManagerV2.personalAuthData.isIDCardPortraitFaceUpload = false
viewBinding.evRealName.clearEditContent()
viewBinding.evIdCardNumber.clearEditContent()
LifeAccountAuthDataManagerV2.personalAuthData.realName = ""
LifeAccountAuthDataManagerV2.personalAuthData.idCardNum = ""
} else {
File(cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE).apply {
if (exists()) delete()
}
LifeAccountAuthDataManagerV2.personalAuthData.isIDCardNationalEmblemFaceUpload = false
}
// 检查下一步条件
if (authType == Constant.TYPE_AUTH_PERSONAL) {
(activity as LifeAccountPersonalAuthActivity).checkNextCondition()
} else {
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
}
override fun onTextClear(from: LifeAccountAuthIdentityInfoEditView) {
when (from) {
viewBinding.evRealName -> {
LifeAccountAuthDataManagerV2.personalAuthData.realName = ""
}
viewBinding.evIdCardNumber -> {
LifeAccountAuthDataManagerV2.personalAuthData.idCardNum = ""
}
viewBinding.evMobile -> {
LifeAccountAuthDataManagerV2.personalAuthData.phoneNum = ""
}
}
// 检查下一步条件
if (authType == Constant.TYPE_AUTH_PERSONAL) {
(activity as LifeAccountPersonalAuthActivity).checkNextCondition()
} else {
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
}
override fun onTextChange(from: LifeAccountAuthIdentityInfoEditView, text: String) {
when (from) {
viewBinding.evRealName -> {
LifeAccountAuthDataManagerV2.personalAuthData.realName = text
}
viewBinding.evIdCardNumber -> {
LifeAccountAuthDataManagerV2.personalAuthData.idCardNum = text
}
viewBinding.evMobile -> {
LifeAccountAuthDataManagerV2.personalAuthData.phoneNum = text
}
}
// 检查下一步条件
if (authType == Constant.TYPE_AUTH_PERSONAL) {
(activity as LifeAccountPersonalAuthActivity).checkNextCondition()
} else {
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
}
override fun onStartFaceAuth() {
// 判断是否满足条件进行活体检测
if (!checkFaceAuthCondition()) {
ToastUtil.showToast(activity, "请补全信息后重试")
return
}
// 判断camera权限
RxPermissions(this).request(Manifest.permission.CAMERA).subscribe {
if (it) {
when (authType) {
Constant.TYPE_AUTH_PERSONAL -> {
// 提交个人认证身份信息
ApiService.authPersonalCheck(
this,
LifeAccountAuthDataManagerV2.generateAuthPersonalCheckRequest()
)
}
Constant.TYPE_AUTH_INDIVIDUAL_BUSINESS -> {
// 提交企业认证身份信息
ApiService.authIndividualBusinessIdentityCommit(
this,
LifeAccountAuthDataManagerV2.generateAuthIndividualBusinessIdentityCommitRequest()
)
}
}
} else {
ToastUtil.showToast(activity, "请在设置里同意相关权限")
}
}
}
override fun authIndividualBusinessIdentityCommitSuccess() {
// 身份信息校验成功后才允许进行人脸验证
XInsight.startLiveVerify(
activity,
LifeAccountAuthDataManagerV2.personalAuthData.idCardNum,
LifeAccountAuthDataManagerV2.personalAuthData.realName,
Constant.TYPE_MEG_LIVE, this
)
}
override fun authIndividualBusinessIdentityCommitFailure(message: String?) {
// 展示输入框下错误提示
when (message) {
Constant.ERROR_MESSAGE_REAL_NAME -> {
viewBinding.evRealName.showErrorTips(
resources.getText(R.string.id_card_name_error_tips) as String
)
viewBinding.evRealName.highLightEditContent()
}
Constant.ERROR_MESSAGE_ID_CARD_NUMBER -> {
viewBinding.evIdCardNumber.showErrorTips(resources.getText(R.string.id_card_number_error_tips) as String)
viewBinding.evIdCardNumber.highLightEditContent()
}
}
}
override fun authEnterpriseLiveIdentitySuccess() {
}
override fun authEnterpriseLiveIdentityFailure(message: String?) {
}
/**
* 本地校验是否可以进行人脸验证
* 必须同时满足真实姓名已填、身份证号已填、身份证两面已上传、职业标签已选(只有个人认证需要)
*/
private fun checkFaceAuthCondition(): Boolean {
if (authType == Constant.TYPE_AUTH_PERSONAL) {
return !LifeAccountAuthDataManagerV2.personalAuthData.occupation.isNullOrEmpty()
&& !LifeAccountAuthDataManagerV2.personalAuthData.realName.isNullOrEmpty()
&& !LifeAccountAuthDataManagerV2.personalAuthData.idCardNum.isNullOrEmpty()
&& LifeAccountAuthDataManagerV2.personalAuthData.isIDCardPortraitFaceUpload
&& LifeAccountAuthDataManagerV2.personalAuthData.isIDCardNationalEmblemFaceUpload
}
return !LifeAccountAuthDataManagerV2.personalAuthData.realName.isNullOrEmpty()
&& !LifeAccountAuthDataManagerV2.personalAuthData.idCardNum.isNullOrEmpty()
&& LifeAccountAuthDataManagerV2.personalAuthData.isIDCardPortraitFaceUpload
&& LifeAccountAuthDataManagerV2.personalAuthData.isIDCardNationalEmblemFaceUpload
}
override fun onCheckPrivacyAgreement(isCheck: Boolean) {
LifeAccountAuthDataManagerV2.personalAuthData.isAgreePrivacyAgreement = isCheck
// 检查下一步条件
if (authType == Constant.TYPE_AUTH_PERSONAL) {
(activity as LifeAccountPersonalAuthActivity).checkNextCondition()
} else {
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
}
// 活体认证回调
override fun onSucceed(liveVerityResult: LiveVerityResult?, result: String?) {
if (liveVerityResult?.verify_result == true) {
// 保存人脸验证结果
LifeAccountAuthDataManagerV2.personalAuthData.isFaceAuthPass = true
// 人脸验证通过UI
viewBinding.avFaceAuth.showFaceAuthResult(true)
// 人脸验证通过锁定信息
lockPersonalAuthInfo()
// 回调server 保存活体识别认证状态
if (authType == Constant.TYPE_AUTH_PERSONAL) {
ApiService.authLiveIdentity(this@LifeAccountIDCardAuthFragmentV2)
// 检查下一步条件
activity?.let { (it as LifeAccountPersonalAuthActivity).checkNextCondition() }
} else {
ApiService.authEnterpriseLiveIdentity(
this@LifeAccountIDCardAuthFragmentV2,
hashMapOf("record_id" to LifeAccountAuthDataManagerV2.merchantAuthData.authRecordId.toString())
)
// 检查下一步条件
activity?.let { (it as LifeAccountEnterpriseAuthActivity).checkNextCondition() }
}
}
}
override fun onFail(code: Int, errMsg: String?, errDomain: String?) {
LifeAccountAuthDataManagerV2.personalAuthData.isFaceAuthPass = false
viewBinding.avFaceAuth.showFaceAuthResult(false)
}
override fun onUploadTask(imageUrl: String?) {
}
}
......@@ -41,7 +41,7 @@ class LifeAccountPersonalAuthActivity :
/**
* 当前fragment
*/
private lateinit var curFragment: LifeAccountIDCardAuthFragment
private lateinit var curFragment: LifeAccountIDCardAuthFragmentV2
/**
* 认证数据 还原认证流程用
......@@ -92,11 +92,11 @@ class LifeAccountPersonalAuthActivity :
private fun initData() {
// 如果有已存在的认证流程则还原进度
authData?.let { LifeAccountAuthDataManager.generatePersonalAuthData(it) }
authData?.let { LifeAccountAuthDataManagerV2.generatePersonalAuthData(it) }
authData?.occupation?.let { viewBind.svOccupation.setContentResult(it) }
curFragment = LifeAccountIDCardAuthFragment()
curFragment = LifeAccountIDCardAuthFragmentV2()
val bundle = Bundle()
bundle.putSerializable(LifeAccountIDCardAuthFragment.EXTRA_AUTH_DATA, authData)
bundle.putSerializable(LifeAccountIDCardAuthFragmentV2.EXTRA_AUTH_DATA, authData)
curFragment.arguments = bundle
supportFragmentManager.beginTransaction()
.add(R.id.fragment_container, curFragment).commit()
......@@ -106,9 +106,9 @@ class LifeAccountPersonalAuthActivity :
* 检查是否可以进行下一步
*/
fun checkNextCondition() {
if (LifeAccountAuthDataManager.personalAuthData.isAgreePrivacyAgreement
&& !LifeAccountAuthDataManager.personalAuthData.occupation.isNullOrEmpty()
&& LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass
if (LifeAccountAuthDataManagerV2.personalAuthData.isAgreePrivacyAgreement
&& !LifeAccountAuthDataManagerV2.personalAuthData.occupation.isNullOrEmpty()
&& LifeAccountAuthDataManagerV2.personalAuthData.isFaceAuthPass
) {
viewBind.tvNext.alpha = 1f
viewBind.tvNext.isEnabled = true
......@@ -130,14 +130,14 @@ class LifeAccountPersonalAuthActivity :
* 避免在升级企业认证时出现数据异常
*/
private fun clearLifeAccountAuthData() {
LifeAccountAuthDataManager.personalAuthData.isAgreePrivacyAgreement = false
LifeAccountAuthDataManager.personalAuthData.occupation = null
LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass = false
LifeAccountAuthDataManager.personalAuthData.realName = null
LifeAccountAuthDataManager.personalAuthData.idCardNum = null
LifeAccountAuthDataManager.personalAuthData.occupation = null
LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload = false
LifeAccountAuthDataManager.personalAuthData.isIDCardNationalEmblemFaceUpload = false
LifeAccountAuthDataManagerV2.personalAuthData.isAgreePrivacyAgreement = false
LifeAccountAuthDataManagerV2.personalAuthData.occupation = null
LifeAccountAuthDataManagerV2.personalAuthData.isFaceAuthPass = false
LifeAccountAuthDataManagerV2.personalAuthData.realName = null
LifeAccountAuthDataManagerV2.personalAuthData.idCardNum = null
LifeAccountAuthDataManagerV2.personalAuthData.occupation = null
LifeAccountAuthDataManagerV2.personalAuthData.isIDCardPortraitFaceUpload = false
LifeAccountAuthDataManagerV2.personalAuthData.isIDCardNationalEmblemFaceUpload = false
}
override fun onClick(v: View?) {
......@@ -192,7 +192,7 @@ class LifeAccountPersonalAuthActivity :
when (event?.name) {
XEventConfig.CHOOSE_CAREER -> {
val selectedCareer = event.body as String
LifeAccountAuthDataManager.personalAuthData.occupation = selectedCareer
LifeAccountAuthDataManagerV2.personalAuthData.occupation = selectedCareer
viewBind.svOccupation.setContentResult(selectedCareer)
checkNextCondition()
}
......@@ -206,7 +206,7 @@ class LifeAccountPersonalAuthActivity :
// 清空职业标签回显
viewBind.svOccupation.clearContentResult()
// 清空身份信息页 直接替换fragment
val targetFragment = LifeAccountIDCardAuthFragment()
val targetFragment = LifeAccountIDCardAuthFragmentV2()
supportFragmentManager.beginTransaction().remove(curFragment).add(R.id.fragment_container, targetFragment).commit()
curFragment = targetFragment
}
......
......@@ -21,9 +21,13 @@ object FileUtil {
if (uri != null) {
val file = File(path)
if (file.exists()) file.delete()
file.parentFile?.mkdirs()
if (file.parentFile?.exists() == false) file.parentFile?.mkdirs()
file.createNewFile()
context?.contentResolver?.openInputStream(uri)?.copyTo(FileOutputStream(path))
val inputStream = context?.contentResolver?.openInputStream(uri)
val outputStream = FileOutputStream(path)
inputStream?.copyTo(outputStream)
inputStream?.close()
outputStream.close()
}
}
......@@ -35,9 +39,11 @@ object FileUtil {
fun copyFileFromAssets(context: Context?, assetFileName: String, destPath: String) {
val file = File(destPath)
if (file.exists()) file.delete()
file.parentFile?.mkdirs()
if (file.parentFile?.exists() == false) file.parentFile?.mkdirs()
file.createNewFile()
context?.assets?.open(assetFileName)?.copyTo(FileOutputStream(file))
val outputStream = FileOutputStream(file)
context?.assets?.open(assetFileName)?.copyTo(outputStream)
outputStream.close()
}
/**
......@@ -49,7 +55,7 @@ object FileUtil {
if (data.isNullOrEmpty()) return
val file = File(destPath)
if (file.exists()) file.delete()
file.parentFile?.mkdirs()
if (file.parentFile?.exists() == false) file.parentFile?.mkdirs()
file.createNewFile()
File(destPath).writeText(data)
}
......
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