Commit 5a9c632b authored by yinjiacheng's avatar yinjiacheng

update 生活号认证信息输入字符过滤

parent 5360c59a
......@@ -6,6 +6,7 @@ import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.text.InputFilter
import android.util.Log
import android.view.LayoutInflater
import android.view.View
......@@ -26,6 +27,7 @@ import com.yidian.shenghuoquan.newscontent.http.httpbean.IBusinessLicenseOCRCall
import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog
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.utils.KS3Core
import com.yidian.shenghuoquan.newscontent.widget.LifeAccountAuthBusinessInfoEditView
import java.io.File
......@@ -36,281 +38,283 @@ import java.io.File
* description: 生活号认证 营业执照认证
*/
class LifeAccountBusinessLicenseAuthFragment :
BaseFragment<FragmentLifeAccountBusinessLicenseAuthBinding>(), View.OnClickListener,
BottomSelectAdapter.OnItemClickListener<BottomSelectBean>, KS3Core.OnKS3TaskListener,
IBusinessLicenseOCRCallback,
LifeAccountAuthBusinessInfoEditView.OnLifeAccountAuthBusinessInfoEditViewCallback {
companion object {
// 认证数据
const val EXTRA_AUTH_DATA = "authData"
}
/**
* sdcard/Android/data/package/cache
*/
private val commonPath by lazy { activity?.externalCacheDir?.absolutePath }
/**
* 调用系统相机拍照,照片保存位置的Uri
*/
private var photoUri: Uri? = null
override fun createViewBinding(
inflater: LayoutInflater,
container: ViewGroup?
): FragmentLifeAccountBusinessLicenseAuthBinding {
return FragmentLifeAccountBusinessLicenseAuthBinding.inflate(inflater, container, false)
}
override fun init(savedInstanceState: Bundle?) {
super.init(savedInstanceState)
initView()
initListener()
initData()
}
private fun initView() {
}
private fun initListener() {
viewBinding.clBusinessLicenseUpload.setOnClickListener(this)
viewBinding.ivClear.setOnClickListener(this)
viewBinding.evRegistrationName.setOnLifeAccountAuthBusinessInfoEditViewCallback(this)
viewBinding.evRegistrationCode.setOnLifeAccountAuthBusinessInfoEditViewCallback(this)
}
private fun initData() {
// 还原认证数据
val authData =
arguments?.getSerializable(EXTRA_AUTH_DATA) ?: return
fillAuthInfo(authData as AuthMerchantCheckBean.Response)
}
/**
* 认证流程中断,下次进入认证流程时还原进度
*/
private fun fillAuthInfo(data: AuthMerchantCheckBean.Response) {
// 营业执照区域
Glide.with(this).load(data.entterprise_image_url).into(viewBinding.ivBusinessLicense)
viewBinding.ivClear.isVisible = true
viewBinding.clBusinessLicenseUpload.isEnabled = false
// 填入注册名称和注册码
viewBinding.evRegistrationName.fillEditContent(data.name)
viewBinding.evRegistrationCode.fillEditContent(data.code)
BaseFragment<FragmentLifeAccountBusinessLicenseAuthBinding>(), View.OnClickListener,
BottomSelectAdapter.OnItemClickListener<BottomSelectBean>, KS3Core.OnKS3TaskListener,
IBusinessLicenseOCRCallback,
LifeAccountAuthBusinessInfoEditView.OnLifeAccountAuthBusinessInfoEditViewCallback {
companion object {
// 认证数据
const val EXTRA_AUTH_DATA = "authData"
}
/**
* sdcard/Android/data/package/cache
*/
private val commonPath by lazy { activity?.externalCacheDir?.absolutePath }
/**
* 调用系统相机拍照,照片保存位置的Uri
*/
private var photoUri: Uri? = null
override fun createViewBinding(
inflater: LayoutInflater,
container: ViewGroup?
): FragmentLifeAccountBusinessLicenseAuthBinding {
return FragmentLifeAccountBusinessLicenseAuthBinding.inflate(inflater, container, false)
}
override fun init(savedInstanceState: Bundle?) {
super.init(savedInstanceState)
initView()
initListener()
initData()
}
private fun initView() {
// 输入过滤
viewBinding.evRegistrationName.setInputFilters(InputFilterUtil.getRegistrationNameFilter(), InputFilter.LengthFilter(40))
viewBinding.evRegistrationCode.setInputFilters(InputFilterUtil.getRegistrationCodeFilter(), InputFilter.LengthFilter(18))
}
private fun initListener() {
viewBinding.clBusinessLicenseUpload.setOnClickListener(this)
viewBinding.ivClear.setOnClickListener(this)
viewBinding.evRegistrationName.setOnLifeAccountAuthBusinessInfoEditViewCallback(this)
viewBinding.evRegistrationCode.setOnLifeAccountAuthBusinessInfoEditViewCallback(this)
}
private fun initData() {
// 还原认证数据
val authData =
arguments?.getSerializable(EXTRA_AUTH_DATA) ?: return
fillAuthInfo(authData as AuthMerchantCheckBean.Response)
}
/**
* 认证流程中断,下次进入认证流程时还原进度
*/
private fun fillAuthInfo(data: AuthMerchantCheckBean.Response) {
// 营业执照区域
Glide.with(this).load(data.entterprise_image_url).into(viewBinding.ivBusinessLicense)
viewBinding.ivClear.isVisible = true
viewBinding.clBusinessLicenseUpload.isEnabled = false
// 填入注册名称和注册码
viewBinding.evRegistrationName.fillEditContent(data.name)
viewBinding.evRegistrationCode.fillEditContent(data.code)
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.cl_business_license_upload -> {
// 弹出上传方式选择
context?.let {
BottomSelectDialog(
it,
this,
arrayListOf(
BottomSelectBean(Constant.ITEM_TAKE_PHOTO),
BottomSelectBean(Constant.ITEM_OPEN_ALBUM)
)
).show()
}
}
R.id.iv_clear -> {
clearBusinessLicenseInfo()
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.cl_business_license_upload -> {
// 弹出上传方式选择
context?.let {
BottomSelectDialog(
it,
this,
arrayListOf(
BottomSelectBean(Constant.ITEM_TAKE_PHOTO),
BottomSelectBean(Constant.ITEM_OPEN_ALBUM)
)
).show()
}
}
R.id.iv_clear -> {
clearBusinessLicenseInfo()
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
}
}
override fun onItemClick(view: View, position: Int, data: BottomSelectBean) {
when (data.item) {
Constant.ITEM_TAKE_PHOTO -> {
// 调用系统相机进行营业执照采集
val file = File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE_CAMERA)
if (file.exists()) file.delete()
file.parentFile?.mkdirs()
file.createNewFile()
photoUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//适配Android 7.0文件权限,通过FileProvider创建一个content类型的Uri
activity?.let {
FileProvider.getUriForFile(
it,
"${activity?.packageName}.provider",
file
)
}
} else {
Uri.fromFile(file)
}
startActivityForResult(
Intent(MediaStore.ACTION_IMAGE_CAPTURE).putExtra(
MediaStore.EXTRA_OUTPUT,
photoUri
),
Constant.REQUEST_CODE_OPEN_CAMERA
)
}
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) {
val uri = if (requestCode == Constant.REQUEST_CODE_OPEN_ALBUM) data?.data else photoUri
val bitmap =
BitmapUtil.generateBitmapFromUri(activity, uri, viewBinding.ivBusinessLicense)
viewBinding.ivBusinessLicense.setImageBitmap(bitmap)
FileUtil.generateFileFromUri(
activity, uri,
commonPath + Constant.FILE_PATH_BUSINESS_LICENSE
}
override fun onItemClick(view: View, position: Int, data: BottomSelectBean) {
when (data.item) {
Constant.ITEM_TAKE_PHOTO -> {
// 调用系统相机进行营业执照采集
val file = File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE_CAMERA)
if (file.exists()) file.delete()
file.parentFile?.mkdirs()
file.createNewFile()
photoUri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
//适配Android 7.0文件权限,通过FileProvider创建一个content类型的Uri
activity?.let {
FileProvider.getUriForFile(
it,
"${activity?.packageName}.provider",
file
)
// 删除从相机拍摄的照片
if (requestCode == Constant.REQUEST_CODE_OPEN_CAMERA) File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE_CAMERA).delete()
// 显示清除按钮
viewBinding.ivClear.visibility = View.VISIBLE
// 上传区域不可点击
viewBinding.clBusinessLicenseUpload.isEnabled = false
// 执行上传金山云
startUpload()
}
} else {
Uri.fromFile(file)
}
}
/**
* 执行营业执照上传金山云
*/
private fun startUpload() {
// 上传前压缩图像
BitmapUtil.compressImage(
commonPath + Constant.FILE_PATH_BUSINESS_LICENSE,
10
startActivityForResult(
Intent(MediaStore.ACTION_IMAGE_CAPTURE).putExtra(
MediaStore.EXTRA_OUTPUT,
photoUri
),
Constant.REQUEST_CODE_OPEN_CAMERA
)
KS3Core.INSTANCE.uploadObject(
File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE),
KS3Core.ObjectType.IMAGE,
KS3Core.ScenarioType.BUSINESS_LICENSE,
this
}
Constant.ITEM_OPEN_ALBUM -> {
// 打开系统相册
startActivityForResult(
Intent(Intent.ACTION_PICK).setDataAndType(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
"image/*"
),
Constant.REQUEST_CODE_OPEN_ALBUM
)
}
}
/**
* 执行营业执照OCR
*/
private fun startBusinessLicenseOCR(objectKey: String?, bucket: String?) {
if (objectKey == null || bucket == null) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"business license objectKey or bucket is null, ocr suspend!"
)
return
}
val requestParams = HashMap<String, String?>()
requestParams["business_image_objectid"] = objectKey
requestParams["business_image_bucket"] = bucket
ApiService.businessLicenseOCR(this, requestParams)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
val uri = if (requestCode == Constant.REQUEST_CODE_OPEN_ALBUM) data?.data else photoUri
val bitmap =
BitmapUtil.generateBitmapFromUri(activity, uri, viewBinding.ivBusinessLicense)
viewBinding.ivBusinessLicense.setImageBitmap(bitmap)
FileUtil.generateFileFromUri(
activity, uri,
commonPath + Constant.FILE_PATH_BUSINESS_LICENSE
)
// 删除从相机拍摄的照片
if (requestCode == Constant.REQUEST_CODE_OPEN_CAMERA) File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE_CAMERA).delete()
// 显示清除按钮
viewBinding.ivClear.visibility = View.VISIBLE
// 上传区域不可点击
viewBinding.clBusinessLicenseUpload.isEnabled = false
// 执行上传金山云
startUpload()
}
/**
* 清除已输入的营业执照相关信息
* 用户更换商户类型操作
*/
fun clearBusinessLicenseInfo() {
// 清除已上传的营业执照
viewBinding.ivBusinessLicense.setImageDrawable(null)
// 清除错误提示
viewBinding.tvUploadErrorTips.isVisible = false
viewBinding.ivClear.isVisible = false
// 清除OCR或用户输入内容
viewBinding.evRegistrationName.clearEditContent()
viewBinding.evRegistrationCode.clearEditContent()
// 设置上传区域可点击
viewBinding.clBusinessLicenseUpload.isEnabled = true
LifeAccountAuthDataManager.merchantAuthData.isBusinessLicenseUpload = false
LifeAccountAuthDataManager.merchantAuthData.registrationName = ""
LifeAccountAuthDataManager.merchantAuthData.registrationCode = ""
}
/**
* 执行营业执照上传金山云
*/
private fun startUpload() {
// 上传前压缩图像
BitmapUtil.compressImage(
commonPath + Constant.FILE_PATH_BUSINESS_LICENSE,
10
)
KS3Core.INSTANCE.uploadObject(
File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE),
KS3Core.ObjectType.IMAGE,
KS3Core.ScenarioType.BUSINESS_LICENSE,
this
)
}
/**
* 执行营业执照OCR
*/
private fun startBusinessLicenseOCR(objectKey: String?, bucket: String?) {
if (objectKey == null || bucket == null) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"business license objectKey or bucket is null, ocr suspend!"
)
return
}
override fun onTaskStart() {
val requestParams = HashMap<String, String?>()
requestParams["business_image_objectid"] = objectKey
requestParams["business_image_bucket"] = bucket
ApiService.businessLicenseOCR(this, requestParams)
}
/**
* 清除已输入的营业执照相关信息
* 用户更换商户类型操作
*/
fun clearBusinessLicenseInfo() {
// 清除已上传的营业执照
viewBinding.ivBusinessLicense.setImageDrawable(null)
// 清除错误提示
viewBinding.tvUploadErrorTips.isVisible = false
viewBinding.ivClear.isVisible = false
// 清除OCR或用户输入内容
viewBinding.evRegistrationName.clearEditContent()
viewBinding.evRegistrationCode.clearEditContent()
// 设置上传区域可点击
viewBinding.clBusinessLicenseUpload.isEnabled = true
LifeAccountAuthDataManager.merchantAuthData.isBusinessLicenseUpload = false
LifeAccountAuthDataManager.merchantAuthData.registrationName = ""
LifeAccountAuthDataManager.merchantAuthData.registrationCode = ""
}
override fun onTaskStart() {
}
override fun onTaskProgress(progress: Double) {
}
override fun onTaskFinish() {
}
override fun onTaskCancel() {
}
override fun onTaskSuccess(bucket: String?, objectKey: String?) {
LifeAccountAuthDataManager.merchantAuthData.isBusinessLicenseUpload = true
LifeAccountAuthDataManager.merchantAuthData.businessLicenseObjectKey = objectKey
// 执行营业执照OCR
startBusinessLicenseOCR(objectKey, bucket)
}
override fun onTaskFailure(statesCode: Int, message: String?) {
}
override fun businessLicenseOCRSuccess(result: BusinessLicenseOCRBean.Response?) {
result?.let { LifeAccountAuthDataManager.generateMerchantAuthData(it) }
// 回显OCR结果
viewBinding.evRegistrationName.fillEditContent(result?.name)
viewBinding.evRegistrationCode.fillEditContent(result?.code)
// 此时营业执照已上传并OCR识别完成 删除本地临时存储文件
File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE).delete()
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
override fun businessLicenseOCRFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request business license ocr failure, message: $message"
)
// 营业执照OCR识别失败提示
viewBinding.tvUploadErrorTips.isVisible = true
viewBinding.tvUploadErrorTips.text =
resources.getString(R.string.check_business_license_distinct)
}
override fun onTextClear(from: LifeAccountAuthBusinessInfoEditView) {
if (from == viewBinding.evRegistrationName) {
LifeAccountAuthDataManager.merchantAuthData.registrationName = ""
} else {
LifeAccountAuthDataManager.merchantAuthData.registrationCode = ""
}
override fun onTaskProgress(progress: Double) {
}
override fun onTaskFinish() {
}
override fun onTaskCancel() {
}
override fun onTaskSuccess(bucket: String?, objectKey: String?) {
LifeAccountAuthDataManager.merchantAuthData.isBusinessLicenseUpload = true
LifeAccountAuthDataManager.merchantAuthData.businessLicenseObjectKey = objectKey
// 执行营业执照OCR
startBusinessLicenseOCR(objectKey, bucket)
}
override fun onTaskFailure(statesCode: Int, message: String?) {
}
override fun businessLicenseOCRSuccess(result: BusinessLicenseOCRBean.Response?) {
result?.let { LifeAccountAuthDataManager.generateMerchantAuthData(it) }
// 回显OCR结果
viewBinding.evRegistrationName.fillEditContent(result?.name)
viewBinding.evRegistrationCode.fillEditContent(result?.code)
// 此时营业执照已上传并OCR识别完成 删除本地临时存储文件
File(commonPath + Constant.FILE_PATH_BUSINESS_LICENSE).delete()
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
override fun businessLicenseOCRFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request business license ocr failure, message: $message"
)
// 营业执照OCR识别失败提示
viewBinding.tvUploadErrorTips.isVisible = true
viewBinding.tvUploadErrorTips.text =
resources.getString(R.string.check_business_license_distinct)
}
override fun onTextClear(from: LifeAccountAuthBusinessInfoEditView) {
if (from == viewBinding.evRegistrationName) {
LifeAccountAuthDataManager.merchantAuthData.registrationName = ""
} else {
LifeAccountAuthDataManager.merchantAuthData.registrationCode = ""
}
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
override fun onTextChange(from: LifeAccountAuthBusinessInfoEditView, text: String) {
if (from == viewBinding.evRegistrationName) {
LifeAccountAuthDataManager.merchantAuthData.registrationName = text
} else {
LifeAccountAuthDataManager.merchantAuthData.registrationCode = text
}
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
override fun onTextChange(from: LifeAccountAuthBusinessInfoEditView, text: String) {
if (from == viewBinding.evRegistrationName) {
LifeAccountAuthDataManager.merchantAuthData.registrationName = text
} else {
LifeAccountAuthDataManager.merchantAuthData.registrationCode = text
}
}
\ No newline at end of file
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
}
......@@ -5,6 +5,7 @@ import android.content.Intent
import android.graphics.BitmapFactory
import android.os.Bundle
import android.provider.MediaStore
import android.text.InputFilter
import android.util.Log
import android.view.LayoutInflater
import android.view.View
......@@ -33,6 +34,7 @@ import com.yidian.shenghuoquan.newscontent.http.httpbean.*
import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog
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.utils.KS3Core
import com.yidian.shenghuoquan.newscontent.widget.LifeAccountAuthIdentityInfoEditView
import com.yidian.shenghuoquan.newscontent.widget.LifeAccountAuthImageView
......@@ -46,784 +48,788 @@ import java.io.File
* description: 生活号身份证认证
*/
class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuthBinding>(),
View.OnClickListener, BottomSelectAdapter.OnItemClickListener<BottomSelectBean>,
IGetIDCardOCRCallback, AuthPersonalGetTokenCallback, IdentifyIdOcrVerifyCallback, PreCallback,
DetectCallback, KS3Core.OnKS3TaskListener, IAuthPersonalCheckCallback,
IAuthLiveIdentityCallback, LifeAccountAuthImageView.OnLifeAccountAuthImageViewCallback,
LifeAccountAuthIdentityInfoEditView.OnLifeAccountAuthIdentityInfoEditViewCallback,
IAuthIndividualBusinessIdentityCommitCallback, IAuthEnterpriseLiveIdentityCallback,
LifeAccountFaceAuthView.OnLifeAccountFaceAuthCallback {
companion object {
// 身份证采集页面回传数据
private const val EXTRA_NAME_ID_CARD_IMAGE = "idcardimg_bitmap"
// 活体检测模型文件名称
private const val FILE_NAME_ALIVE_DETECT_MODEL = "faceidmodel.bin"
//活体检测语种 详见文档
private const val ALIVE_DETECT_LANGUAGE = "zh"
//活体检测请求host 详见文档
private const val ALIVE_DETECT_HOST = "https://api.megvii.com"
// 认证数据
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 }
/***
* sdcard/Android/data/package/file/face_id
*/
private val fileFaceIDPath by lazy { activity?.getExternalFilesDir("face_id")?.absolutePath }
/**
* 旷视活体检测
*/
private val megLiveManager by lazy { MegLiveManager.getInstance() }
/**
* 当前认证类型
*/
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()
initFaceID()
}
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)
}
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)
}
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)
}
}
/**
* 初始化旷视FaceID
*/
private fun initFaceID() {
// 身份证采集初始化
// 竖屏采集
Configuration.setIsVertical(activity, true)
// 检查license是否有效
checkFaceIDLicense()
// 若活体检测模型文件不存在则从assets中拷贝
if (!File(fileFaceIDPath + File.separator + FILE_NAME_ALIVE_DETECT_MODEL).exists()) {
FileUtil.copyFileFromAssets(
activity,
FILE_NAME_ALIVE_DETECT_MODEL,
fileFaceIDPath + File.separator + FILE_NAME_ALIVE_DETECT_MODEL
View.OnClickListener, BottomSelectAdapter.OnItemClickListener<BottomSelectBean>,
IGetIDCardOCRCallback, AuthPersonalGetTokenCallback, IdentifyIdOcrVerifyCallback, PreCallback,
DetectCallback, KS3Core.OnKS3TaskListener, IAuthPersonalCheckCallback,
IAuthLiveIdentityCallback, LifeAccountAuthImageView.OnLifeAccountAuthImageViewCallback,
LifeAccountAuthIdentityInfoEditView.OnLifeAccountAuthIdentityInfoEditViewCallback,
IAuthIndividualBusinessIdentityCommitCallback, IAuthEnterpriseLiveIdentityCallback,
LifeAccountFaceAuthView.OnLifeAccountFaceAuthCallback {
companion object {
// 身份证采集页面回传数据
private const val EXTRA_NAME_ID_CARD_IMAGE = "idcardimg_bitmap"
// 活体检测模型文件名称
private const val FILE_NAME_ALIVE_DETECT_MODEL = "faceidmodel.bin"
//活体检测语种 详见文档
private const val ALIVE_DETECT_LANGUAGE = "zh"
//活体检测请求host 详见文档
private const val ALIVE_DETECT_HOST = "https://api.megvii.com"
// 认证数据
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 }
/***
* sdcard/Android/data/package/file/face_id
*/
private val fileFaceIDPath by lazy { activity?.getExternalFilesDir("face_id")?.absolutePath }
/**
* 旷视活体检测
*/
private val megLiveManager by lazy { MegLiveManager.getInstance() }
/**
* 当前认证类型
*/
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()
initFaceID()
}
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))
viewBinding.evIdCardNumber.setInputFilters(InputFilterUtil.getIDCardNumberFilter(), InputFilter.LengthFilter(18))
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)
}
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)
}
}
/**
* 初始化旷视FaceID
*/
private fun initFaceID() {
// 身份证采集初始化
// 竖屏采集
Configuration.setIsVertical(activity, true)
// 检查license是否有效
checkFaceIDLicense()
// 若活体检测模型文件不存在则从assets中拷贝
if (!File(fileFaceIDPath + File.separator + FILE_NAME_ALIVE_DETECT_MODEL).exists()) {
FileUtil.copyFileFromAssets(
activity,
FILE_NAME_ALIVE_DETECT_MODEL,
fileFaceIDPath + File.separator + FILE_NAME_ALIVE_DETECT_MODEL
)
}
}
/**
* 检查旷视FaceID授权有效
*/
private fun checkFaceIDLicense(): Boolean {
val licenseManager = IDCardQualityLicenseManager(activity)
if (licenseManager.checkCachedLicense() > 0) {
//已授权或者授权未过期
Log.i(Constant.LIFE_ACCOUNT_AUTH_TAG, "FaceID 授权有效")
return true
} else {
//需要重新授权
Log.i(Constant.LIFE_ACCOUNT_AUTH_TAG, "FaceID 授权无效,开始获取授权")
Thread {
val manager = Manager(activity, true)
manager.registerLicenseManager(licenseManager)
manager.takeLicenseFromNetwork(
licenseManager.getContext(
Configuration.getUUID(activity)
)
)
}.start()
}
return false
}
/**
* 个人认证流程中断,下次进入认证流程时还原进度
*/
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.showFaceAuthSuccess()
// 如果人脸验证已通过 则直接锁定输入状态
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.showFaceAuthSuccess()
// 如果人脸验证已通过 则直接锁定输入状态
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
Configuration.setCardType(activity, Constant.ID_CARD_PORTRAIT_FACE)
activity?.let {
BottomSelectDialog(
it,
this,
arrayListOf(
BottomSelectBean(Constant.ITEM_TAKE_PHOTO),
BottomSelectBean(Constant.ITEM_OPEN_ALBUM)
)
).show()
}
}
/**
* 检查旷视FaceID授权有效
*/
private fun checkFaceIDLicense(): Boolean {
val licenseManager = IDCardQualityLicenseManager(activity)
if (licenseManager.checkCachedLicense() > 0) {
//已授权或者授权未过期
Log.i(Constant.LIFE_ACCOUNT_AUTH_TAG, "FaceID 授权有效")
return true
} else {
//需要重新授权
Log.i(Constant.LIFE_ACCOUNT_AUTH_TAG, "FaceID 授权无效,开始获取授权")
Thread {
val manager = Manager(activity, true)
manager.registerLicenseManager(licenseManager)
manager.takeLicenseFromNetwork(
licenseManager.getContext(
Configuration.getUUID(activity)
)
)
}.start()
}
return false
}
/**
* 个人认证流程中断,下次进入认证流程时还原进度
*/
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.showFaceAuthSuccess()
// 如果人脸验证已通过 则直接锁定输入状态
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.showFaceAuthSuccess()
// 如果人脸验证已通过 则直接锁定输入状态
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
Configuration.setCardType(activity, 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
Configuration.setCardType(activity, 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 -> {
// 调用FaceID进行身份证采集
if (checkFaceIDLicense()) {
startActivityForResult(
Intent(activity, IDCardDetectActivity::class.java),
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
)
startIDCardUpload(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
)
startIDCardUpload(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
)
startIDCardUpload(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
)
startIDCardUpload(Constant.ID_CARD_NATIONAL_EMBLEM_FACE)
}
}
}
}
R.id.iv_id_card_national_emblem_face -> {
// 上传身份证国徽面
curFace = Constant.ID_CARD_NATIONAL_EMBLEM_FACE
Configuration.setCardType(activity, Constant.ID_CARD_NATIONAL_EMBLEM_FACE)
activity?.let {
BottomSelectDialog(
it,
this,
arrayListOf(
BottomSelectBean(Constant.ITEM_TAKE_PHOTO),
BottomSelectBean(Constant.ITEM_OPEN_ALBUM)
)
).show()
}
}
/**
* 执行身份证上传金山云
* @param face 身份证两面标识
*/
private fun startIDCardUpload(face: Int) {
val uploadFile = if (face == Constant.ID_CARD_PORTRAIT_FACE) {
File(cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE)
}
}
}
override fun onItemClick(view: View, position: Int, data: BottomSelectBean) {
when (data.item) {
Constant.ITEM_TAKE_PHOTO -> {
// 调用FaceID进行身份证采集
if (checkFaceIDLicense()) {
startActivityForResult(
Intent(activity, IDCardDetectActivity::class.java),
Constant.REQUEST_CODE_ID_CARD_CAPTURE
)
} else {
File(cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE)
ToastUtil.showToast(activity, "获取授权失败,请稍后重试")
}
KS3Core.INSTANCE.uploadObject(
uploadFile,
KS3Core.ObjectType.IMAGE,
KS3Core.ScenarioType.ID_CARD,
object : KS3Core.OnKS3TaskListener {
override fun onTaskStart() {
}
override fun onTaskProgress(progress: Double) {
}
override fun onTaskFinish() {
}
override fun onTaskCancel() {
}
override fun onTaskSuccess(bucket: String?, objectKey: String?) {
if (face == Constant.ID_CARD_PORTRAIT_FACE) {
LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload =
true
LifeAccountAuthDataManager.personalAuthData.idCardPortraitFaceObjectKey =
objectKey
LifeAccountAuthDataManager.personalAuthData.idCardPortraitFaceBucket =
bucket
} else {
LifeAccountAuthDataManager.personalAuthData.isIDCardNationalEmblemFaceUpload =
true
LifeAccountAuthDataManager.personalAuthData.idCardNationalEmblemFaceObjectKey =
objectKey
LifeAccountAuthDataManager.personalAuthData.idCardNationalEmblemFaceBucket =
bucket
}
startIDCardOCR(face, objectKey, bucket)
}
override fun onTaskFailure(statesCode: Int, message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"upload ID card national emblem face failure, message: $message"
)
}
}
}
Constant.ITEM_OPEN_ALBUM -> {
// 打开系统相册
startActivityForResult(
Intent(Intent.ACTION_PICK).setDataAndType(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
"image/*"
),
Constant.REQUEST_CODE_OPEN_ALBUM
)
}
/**
* 执行身份证OCR
*/
private fun startIDCardOCR(face: Int, objectKey: String?, bucket: String?) {
if (face == Constant.ID_CARD_PORTRAIT_FACE) {
ApiService.getIDCardOCR(
this, hashMapOf(
Pair("posit_image_objectid", objectKey),
Pair("posit_bucket", bucket)
)
}
}
}
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
)
} else {
ApiService.getIDCardOCR(
this, hashMapOf(
Pair("back_image_objectid", objectKey),
Pair("back_bucket", bucket)
)
viewBinding.ivIdCardPortraitFace.addImage(bitmap)
FileUtil.generateFileFromUri(
activity,
data?.data,
cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE
)
}
}
override fun getIDCardOCRSuccess(result: GetIDCardOCRBean.Response?) {
result?.let { LifeAccountAuthDataManager.generatePersonalAuthData(it) }
// 回显OCR结果
viewBinding.evRealName.fillEditContent(result?.posit?.name)
viewBinding.evIdCardNumber.fillEditContent(result?.posit?.idcard_number)
// 此时身份证已上传并OCR识别完成 删除本地临时存储文件
File(cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE).apply {
if (exists()) delete()
}
File(cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE).apply {
if (exists()) delete()
}
}
override fun getIDCardOCRFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request id card ocr failure, message: $message"
)
}
override fun getTokenSuccess(t: HttpResult<AuthPersonalGetTokenBean.Response?>?) {
LifeAccountAuthDataManager.personalAuthData.liveDetectBizToken = t?.result?.biz_token
megLiveManager.preDetect(
activity,
t?.result?.biz_token,
ALIVE_DETECT_LANGUAGE,
ALIVE_DETECT_HOST,
fileFaceIDPath + File.separator + FILE_NAME_ALIVE_DETECT_MODEL,
this
)
}
override fun identifyIdOcrVerifySuccess(t: HttpResult<IdentifyIdOcrVerifyBean.Response?>?) {
if (t?.result?.verify_result == true) {
Log.i(Constant.LIFE_ACCOUNT_AUTH_TAG, "live detect success")
// 保存人脸验证结果
LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass = true
// 人脸验证通过UI
viewBinding.avFaceAuth.showFaceAuthResult(true)
// 删除活体检测数据
File(cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA).apply {
if (exists()) delete()
}
lockPersonalAuthInfo()
// 回调server 保存活体识别认证状态
if (authType == Constant.TYPE_AUTH_PERSONAL) {
ApiService.authLiveIdentity(this)
// 检查下一步条件
(activity as LifeAccountPersonalAuthActivity).checkNextCondition()
} else {
ApiService.authEnterpriseLiveIdentity(
this,
hashMapOf(
Pair(
"record_id",
LifeAccountAuthDataManager.merchantAuthData.authRecordId.toString()
)
)
)
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
}
}
override fun identifyIdOcrVerifyFailure(t: HttpResult<IdentifyIdOcrVerifyBean.Response?>?) {
Log.e(Constant.LIFE_ACCOUNT_AUTH_TAG, "live detect failure, message: ${t?.reason}")
LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass = false
// 人脸验证未通过UI
viewBinding.avFaceAuth.showFaceAuthResult(false)
}
override fun onPreStart() {
// TODO: 6/1/21 show progress
}
override fun onPreFinish(token: String?, errorCode: Int, errorMessage: String?) {
// 只有当完成预处理且errorCode==1000的时候才可以调用startDetect开启活体检测
if (errorCode == 1000) {
megLiveManager.setVerticalDetectionType(MegLiveManager.DETECT_VERITICAL_FRONT)
megLiveManager.startDetect(this)
} else {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"alive detect pre detect failure, errorCode: $errorCode, errorMessage: $errorMessage"
BitmapUtil.compressImage(
cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE,
10
)
}
}
override fun onDetectFinish(
token: String?,
errorCode: Int,
errorMessage: String?,
data: String?
) {
if (errorCode == 1000) {
// 保存活体加密数据 上传金山云
FileUtil.generateFileFromString(
data,
cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA
startIDCardUpload(Constant.ID_CARD_PORTRAIT_FACE)
} else {
val bitmap = BitmapUtil.generateBitmapFromUri(
activity,
data?.data,
viewBinding.ivIdCardNationalEmblemFace
)
KS3Core.INSTANCE.uploadObject(
cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA,
KS3Core.ScenarioType.ALIVE_DETECT,
this
viewBinding.ivIdCardNationalEmblemFace.addImage(bitmap)
FileUtil.generateFileFromUri(
activity,
data?.data,
cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE
)
} else {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"alive detect detect failure, errorCode: $errorCode, errorMessage: $errorMessage"
BitmapUtil.compressImage(
cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE,
10
)
viewBinding.avFaceAuth.showFaceAuthResult(false)
startIDCardUpload(Constant.ID_CARD_NATIONAL_EMBLEM_FACE)
}
}
}
override fun onTaskStart() {
}
override fun onTaskProgress(progress: Double) {
}
override fun onTaskFinish() {
}
override fun onTaskCancel() {
}
override fun onTaskSuccess(bucket: String?, objectKey: String?) {
LifeAccountAuthDataManager.personalAuthData.liveDetectObjectKey = objectKey
LifeAccountAuthDataManager.personalAuthData.liveDetectBucket = bucket
ApiService.identifyIdOcrVerify(
this,
hashMapOf(
Pair(
"biz_token",
LifeAccountAuthDataManager.personalAuthData.liveDetectBizToken
),
Pair("meglive_objectid", objectKey),
Pair("meglive_bucket", bucket)
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
)
)
}
override fun onTaskFailure(statesCode: Int, message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"upload alive detect verify data failure, message: $message"
)
}
override fun authPersonCheckSuccess() {
// 身份信息校验成功后才允许进行人脸验证
// 若存在上一次活体检测数据则删除 处理活体检测失败 再次进入
File(cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA).apply {
if (exists()) delete()
}
// 跳转人脸认证
ApiService.authPersonalGetToken(
this,
hashMapOf(
Pair("id_number", LifeAccountAuthDataManager.personalAuthData.idCardNum),
Pair("id_card_name", LifeAccountAuthDataManager.personalAuthData.realName),
Pair("liveness_type", Constant.TYPE_MEG_LIVE)
startIDCardUpload(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
)
)
}
startIDCardUpload(Constant.ID_CARD_NATIONAL_EMBLEM_FACE)
}
}
}
}
}
/**
* 执行身份证上传金山云
* @param face 身份证两面标识
*/
private fun startIDCardUpload(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)
}
KS3Core.INSTANCE.uploadObject(
uploadFile,
KS3Core.ObjectType.IMAGE,
KS3Core.ScenarioType.ID_CARD,
object : KS3Core.OnKS3TaskListener {
override fun onTaskStart() {
override fun authPersonCheckFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth personal check failure: message: $message"
)
// 展示错误提示
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 onTaskProgress(progress: Double) {
}
}
override fun authLiveIdentityFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth live identity failure: message: $message"
)
}
override fun onTaskFinish() {
override fun onImageClear(from: LifeAccountAuthImageView) {
if (from == viewBinding.ivIdCardPortraitFace) {
// 清除照片时删除本地文件
File(cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE).apply {
if (exists()) delete()
}
LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload = false
viewBinding.evRealName.clearEditContent()
viewBinding.evIdCardNumber.clearEditContent()
LifeAccountAuthDataManager.personalAuthData.realName = ""
LifeAccountAuthDataManager.personalAuthData.idCardNum = ""
} else {
File(cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE).apply {
if (exists()) delete()
}
LifeAccountAuthDataManager.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 -> {
LifeAccountAuthDataManager.personalAuthData.realName = ""
}
viewBinding.evIdCardNumber -> {
LifeAccountAuthDataManager.personalAuthData.idCardNum = ""
}
viewBinding.evMobile -> {
LifeAccountAuthDataManager.personalAuthData.phoneNum = ""
}
}
// 检查下一步条件
if (authType == Constant.TYPE_AUTH_PERSONAL) {
(activity as LifeAccountPersonalAuthActivity).checkNextCondition()
} else {
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
}
override fun onTaskCancel() {
override fun onTextChange(from: LifeAccountAuthIdentityInfoEditView, text: String) {
when (from) {
viewBinding.evRealName -> {
LifeAccountAuthDataManager.personalAuthData.realName = text
}
viewBinding.evIdCardNumber -> {
LifeAccountAuthDataManager.personalAuthData.idCardNum = text
}
viewBinding.evMobile -> {
LifeAccountAuthDataManager.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
override fun onTaskSuccess(bucket: String?, objectKey: String?) {
if (face == Constant.ID_CARD_PORTRAIT_FACE) {
LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload =
true
LifeAccountAuthDataManager.personalAuthData.idCardPortraitFaceObjectKey =
objectKey
LifeAccountAuthDataManager.personalAuthData.idCardPortraitFaceBucket =
bucket
} else {
LifeAccountAuthDataManager.personalAuthData.isIDCardNationalEmblemFaceUpload =
true
LifeAccountAuthDataManager.personalAuthData.idCardNationalEmblemFaceObjectKey =
objectKey
LifeAccountAuthDataManager.personalAuthData.idCardNationalEmblemFaceBucket =
bucket
}
startIDCardOCR(face, objectKey, bucket)
}
when (authType) {
Constant.TYPE_AUTH_PERSONAL -> {
ApiService.authPersonalCheck(
this,
LifeAccountAuthDataManager.generateAuthPersonalCheckRequest()
)
}
Constant.TYPE_AUTH_INDIVIDUAL_BUSINESS -> {
ApiService.authIndividualBusinessIdentityCommit(
this,
LifeAccountAuthDataManager.generateAuthIndividualBusinessIdentityCommitRequest()
)
}
}
}
override fun authIndividualBusinessIdentityCommitSuccess() {
// 身份信息校验成功后才允许进行人脸验证
// 若存在上一次活体检测数据则删除 处理活体检测失败 再次进入
File(cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA).apply {
if (exists()) delete()
override fun onTaskFailure(statesCode: Int, message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"upload ID card national emblem face failure, message: $message"
)
}
// 跳转人脸认证
ApiService.authPersonalGetToken(
this,
hashMapOf(
Pair("id_number", LifeAccountAuthDataManager.personalAuthData.idCardNum),
Pair("id_card_name", LifeAccountAuthDataManager.personalAuthData.realName),
Pair("liveness_type", Constant.TYPE_MEG_LIVE)
}
)
}
/**
* 执行身份证OCR
*/
private fun startIDCardOCR(face: Int, objectKey: String?, bucket: String?) {
if (face == Constant.ID_CARD_PORTRAIT_FACE) {
ApiService.getIDCardOCR(
this, hashMapOf(
Pair("posit_image_objectid", objectKey),
Pair("posit_bucket", bucket)
)
)
} else {
ApiService.getIDCardOCR(
this, hashMapOf(
Pair("back_image_objectid", objectKey),
Pair("back_bucket", bucket)
)
)
}
}
override fun getIDCardOCRSuccess(result: GetIDCardOCRBean.Response?) {
result?.let { LifeAccountAuthDataManager.generatePersonalAuthData(it) }
// 回显OCR结果
viewBinding.evRealName.fillEditContent(result?.posit?.name)
viewBinding.evIdCardNumber.fillEditContent(result?.posit?.idcard_number)
// 此时身份证已上传并OCR识别完成 删除本地临时存储文件
File(cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE).apply {
if (exists()) delete()
}
File(cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE).apply {
if (exists()) delete()
}
}
override fun getIDCardOCRFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request id card ocr failure, message: $message"
)
}
override fun getTokenSuccess(t: HttpResult<AuthPersonalGetTokenBean.Response?>?) {
LifeAccountAuthDataManager.personalAuthData.liveDetectBizToken = t?.result?.biz_token
megLiveManager.preDetect(
activity,
t?.result?.biz_token,
ALIVE_DETECT_LANGUAGE,
ALIVE_DETECT_HOST,
fileFaceIDPath + File.separator + FILE_NAME_ALIVE_DETECT_MODEL,
this
)
}
override fun identifyIdOcrVerifySuccess(t: HttpResult<IdentifyIdOcrVerifyBean.Response?>?) {
if (t?.result?.verify_result == true) {
Log.i(Constant.LIFE_ACCOUNT_AUTH_TAG, "live detect success")
// 保存人脸验证结果
LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass = true
// 人脸验证通过UI
viewBinding.avFaceAuth.showFaceAuthResult(true)
// 删除活体检测数据
File(cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA).apply {
if (exists()) delete()
}
lockPersonalAuthInfo()
// 回调server 保存活体识别认证状态
if (authType == Constant.TYPE_AUTH_PERSONAL) {
ApiService.authLiveIdentity(this)
// 检查下一步条件
(activity as LifeAccountPersonalAuthActivity).checkNextCondition()
} else {
ApiService.authEnterpriseLiveIdentity(
this,
hashMapOf(
Pair(
"record_id",
LifeAccountAuthDataManager.merchantAuthData.authRecordId.toString()
)
)
)
}
override fun authIndividualBusinessIdentityCommitFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth individual business identity commit failure, message: $message"
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
}
}
override fun identifyIdOcrVerifyFailure(t: HttpResult<IdentifyIdOcrVerifyBean.Response?>?) {
Log.e(Constant.LIFE_ACCOUNT_AUTH_TAG, "live detect failure, message: ${t?.reason}")
LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass = false
// 人脸验证未通过UI
viewBinding.avFaceAuth.showFaceAuthResult(false)
}
override fun onPreStart() {
// TODO: 6/1/21 show progress
}
override fun onPreFinish(token: String?, errorCode: Int, errorMessage: String?) {
// 只有当完成预处理且errorCode==1000的时候才可以调用startDetect开启活体检测
if (errorCode == 1000) {
megLiveManager.setVerticalDetectionType(MegLiveManager.DETECT_VERITICAL_FRONT)
megLiveManager.startDetect(this)
} else {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"alive detect pre detect failure, errorCode: $errorCode, errorMessage: $errorMessage"
)
}
}
override fun onDetectFinish(
token: String?,
errorCode: Int,
errorMessage: String?,
data: String?
) {
if (errorCode == 1000) {
// 保存活体加密数据 上传金山云
FileUtil.generateFileFromString(
data,
cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA
)
KS3Core.INSTANCE.uploadObject(
cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA,
KS3Core.ScenarioType.ALIVE_DETECT,
this
)
} else {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"alive detect detect failure, errorCode: $errorCode, errorMessage: $errorMessage"
)
viewBinding.avFaceAuth.showFaceAuthResult(false)
}
}
override fun onTaskStart() {
}
override fun onTaskProgress(progress: Double) {
}
override fun onTaskFinish() {
}
override fun onTaskCancel() {
}
override fun onTaskSuccess(bucket: String?, objectKey: String?) {
LifeAccountAuthDataManager.personalAuthData.liveDetectObjectKey = objectKey
LifeAccountAuthDataManager.personalAuthData.liveDetectBucket = bucket
ApiService.identifyIdOcrVerify(
this,
hashMapOf(
Pair(
"biz_token",
LifeAccountAuthDataManager.personalAuthData.liveDetectBizToken
),
Pair("meglive_objectid", objectKey),
Pair("meglive_bucket", bucket)
)
)
}
override fun onTaskFailure(statesCode: Int, message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"upload alive detect verify data failure, message: $message"
)
}
override fun authPersonCheckSuccess() {
// 身份信息校验成功后才允许进行人脸验证
// 若存在上一次活体检测数据则删除 处理活体检测失败 再次进入
File(cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA).apply {
if (exists()) delete()
}
// 跳转人脸认证
ApiService.authPersonalGetToken(
this,
hashMapOf(
Pair("id_number", LifeAccountAuthDataManager.personalAuthData.idCardNum),
Pair("id_card_name", LifeAccountAuthDataManager.personalAuthData.realName),
Pair("liveness_type", Constant.TYPE_MEG_LIVE)
)
)
}
override fun authPersonCheckFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth personal check failure: message: $message"
)
// 展示错误提示
when (message) {
Constant.ERROR_MESSAGE_REAL_NAME -> {
viewBinding.evRealName.showErrorTips(
resources.getText(R.string.id_card_name_error_tips) as String
)
}
override fun authEnterpriseLiveIdentitySuccess() {
}
override fun authEnterpriseLiveIdentityFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth enterprise live identity failure: message: $message"
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?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth live identity failure: message: $message"
)
}
override fun onImageClear(from: LifeAccountAuthImageView) {
if (from == viewBinding.ivIdCardPortraitFace) {
// 清除照片时删除本地文件
File(cachePath + Constant.FILE_PATH_ID_CARD_PORTRAIT_FACE).apply {
if (exists()) delete()
}
LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload = false
viewBinding.evRealName.clearEditContent()
viewBinding.evIdCardNumber.clearEditContent()
LifeAccountAuthDataManager.personalAuthData.realName = ""
LifeAccountAuthDataManager.personalAuthData.idCardNum = ""
} else {
File(cachePath + Constant.FILE_PATH_ID_CARD_NATIONAL_EMBLEM_FACE).apply {
if (exists()) delete()
}
LifeAccountAuthDataManager.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 -> {
LifeAccountAuthDataManager.personalAuthData.realName = ""
}
viewBinding.evIdCardNumber -> {
LifeAccountAuthDataManager.personalAuthData.idCardNum = ""
}
viewBinding.evMobile -> {
LifeAccountAuthDataManager.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 -> {
LifeAccountAuthDataManager.personalAuthData.realName = text
}
viewBinding.evIdCardNumber -> {
LifeAccountAuthDataManager.personalAuthData.idCardNum = text
}
viewBinding.evMobile -> {
LifeAccountAuthDataManager.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
}
when (authType) {
Constant.TYPE_AUTH_PERSONAL -> {
ApiService.authPersonalCheck(
this,
LifeAccountAuthDataManager.generateAuthPersonalCheckRequest()
)
}
/**
* 本地校验是否可以进行人脸验证
* 必须同时满足真实姓名已填、身份证号已填、身份证两面已上传、职业标签已选(只有个人认证需要)
*/
private fun checkFaceAuthCondition(): Boolean {
if (authType == Constant.TYPE_AUTH_PERSONAL) {
return !LifeAccountAuthDataManager.personalAuthData.occupation.isNullOrEmpty()
&& !LifeAccountAuthDataManager.personalAuthData.realName.isNullOrEmpty()
&& !LifeAccountAuthDataManager.personalAuthData.idCardNum.isNullOrEmpty()
&& LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload
&& LifeAccountAuthDataManager.personalAuthData.isIDCardNationalEmblemFaceUpload
}
return !LifeAccountAuthDataManager.personalAuthData.realName.isNullOrEmpty()
&& !LifeAccountAuthDataManager.personalAuthData.idCardNum.isNullOrEmpty()
&& LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload
&& LifeAccountAuthDataManager.personalAuthData.isIDCardNationalEmblemFaceUpload
}
}
Constant.TYPE_AUTH_INDIVIDUAL_BUSINESS -> {
ApiService.authIndividualBusinessIdentityCommit(
this,
LifeAccountAuthDataManager.generateAuthIndividualBusinessIdentityCommitRequest()
)
}
}
}
override fun authIndividualBusinessIdentityCommitSuccess() {
// 身份信息校验成功后才允许进行人脸验证
// 若存在上一次活体检测数据则删除 处理活体检测失败 再次进入
File(cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA).apply {
if (exists()) delete()
}
// 跳转人脸认证
ApiService.authPersonalGetToken(
this,
hashMapOf(
Pair("id_number", LifeAccountAuthDataManager.personalAuthData.idCardNum),
Pair("id_card_name", LifeAccountAuthDataManager.personalAuthData.realName),
Pair("liveness_type", Constant.TYPE_MEG_LIVE)
)
)
}
override fun authIndividualBusinessIdentityCommitFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth individual business identity commit failure, message: $message"
)
}
override fun authEnterpriseLiveIdentitySuccess() {
}
override fun authEnterpriseLiveIdentityFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth enterprise live identity failure: message: $message"
)
}
/**
* 本地校验是否可以进行人脸验证
* 必须同时满足真实姓名已填、身份证号已填、身份证两面已上传、职业标签已选(只有个人认证需要)
*/
private fun checkFaceAuthCondition(): Boolean {
if (authType == Constant.TYPE_AUTH_PERSONAL) {
return !LifeAccountAuthDataManager.personalAuthData.occupation.isNullOrEmpty()
&& !LifeAccountAuthDataManager.personalAuthData.realName.isNullOrEmpty()
&& !LifeAccountAuthDataManager.personalAuthData.idCardNum.isNullOrEmpty()
&& LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload
&& LifeAccountAuthDataManager.personalAuthData.isIDCardNationalEmblemFaceUpload
}
return !LifeAccountAuthDataManager.personalAuthData.realName.isNullOrEmpty()
&& !LifeAccountAuthDataManager.personalAuthData.idCardNum.isNullOrEmpty()
&& LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload
&& LifeAccountAuthDataManager.personalAuthData.isIDCardNationalEmblemFaceUpload
}
}
......@@ -11,15 +11,80 @@ import java.util.regex.Pattern
*/
object InputFilterUtil {
/**
* 只允许汉字输入
*/
fun getChineseFilter(): InputFilter {
return InputFilter { source, start, end, dest, dstart, dend ->
val pattern = Pattern.compile("[\\u4E00-\\u9FFF]+")
val matcher = pattern.matcher(source.toString())
if (!matcher.matches()) return@InputFilter ""
return@InputFilter null
}
/**
* 只允许汉字输入
*/
fun getChineseFilter(): InputFilter {
return InputFilter { source, start, end, dest, dstart, dend ->
val pattern = Pattern.compile("[\\u4E00-\\u9FFF]+")
val matcher = pattern.matcher(source.toString())
if (!matcher.matches()) return@InputFilter ""
return@InputFilter null
}
}
\ No newline at end of file
}
/**
* 真实姓名过滤
* 汉字 + ·
*/
fun getRealNameFilter(): InputFilter {
return InputFilter { source, start, end, dest, dstart, dend ->
val pattern = Pattern.compile("[\\u4E00-\\u9FFF|·]+")
val matcher = pattern.matcher(source.toString())
if (!matcher.matches()) return@InputFilter ""
return@InputFilter null
}
}
/**
* 身份证号过滤
* 数字 + X
*/
fun getIDCardNumberFilter(): InputFilter {
return InputFilter { source, start, end, dest, dstart, dend ->
val pattern = Pattern.compile("[0-9|X]+")
val matcher = pattern.matcher(source.toString())
if (!matcher.matches()) return@InputFilter ""
return@InputFilter null
}
}
/**
* 手机号过滤
* 数字
*/
fun getPhoneNumberFilter(): InputFilter {
return InputFilter { source, start, end, dest, dstart, dend ->
val pattern = Pattern.compile("[0-9]+")
val matcher = pattern.matcher(source.toString())
if (!matcher.matches()) return@InputFilter ""
return@InputFilter null
}
}
/**
* 公司注册名过滤
* 汉字
*/
fun getRegistrationNameFilter(): InputFilter {
return InputFilter { source, start, end, dest, dstart, dend ->
val pattern = Pattern.compile("[\\u4E00-\\u9FFF]+")
val matcher = pattern.matcher(source.toString())
if (!matcher.matches()) return@InputFilter ""
return@InputFilter null
}
}
/**
* 统一社会信用代码过滤
* 数字 + 大写字母
*/
fun getRegistrationCodeFilter(): InputFilter {
return InputFilter { source, start, end, dest, dstart, dend ->
val pattern = Pattern.compile("[0-9A-Z]+")
val matcher = pattern.matcher(source.toString())
if (!matcher.matches()) return@InputFilter ""
return@InputFilter null
}
}
}
......@@ -3,6 +3,7 @@ package com.yidian.shenghuoquan.newscontent.widget
import android.content.Context
import android.graphics.Color
import android.text.Editable
import android.text.InputFilter
import android.text.TextUtils
import android.text.TextWatcher
import android.util.AttributeSet
......@@ -18,139 +19,146 @@ import com.yidian.shenghuoquan.newscontent.databinding.ViewLifeAccountAuthBusine
* description: 生活号认证 营业执照信息录入
*/
class LifeAccountAuthBusinessInfoEditView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
) : YdConstraintLayout(context, attrs, defStyle), View.OnClickListener, TextWatcher {
private val viewBinding: ViewLifeAccountAuthBusinessInfoEditBinding =
ViewLifeAccountAuthBusinessInfoEditBinding.bind(
View.inflate(
getContext(),
R.layout.view_life_account_auth_business_info_edit,
this
)
)
private var callback: OnLifeAccountAuthBusinessInfoEditViewCallback? = null
/**
* 是否输入错误标识位
*/
private var isInputError = false
init {
val typedArray =
context.obtainStyledAttributes(attrs, R.styleable.LifeAccountAuthBusinessInfoEditView)
viewBinding.tvContent.text =
typedArray.getText(R.styleable.LifeAccountAuthBusinessInfoEditView_LifeAccountAuthBusinessInfoEditView_content_text)
viewBinding.etContent.hint =
typedArray.getText(R.styleable.LifeAccountAuthBusinessInfoEditView_LifeAccountAuthBusinessInfoEditView_hint_text)
typedArray.recycle()
viewBinding.ivClear.setOnClickListener(this)
viewBinding.etContent.addTextChangedListener(this)
private val viewBinding: ViewLifeAccountAuthBusinessInfoEditBinding =
ViewLifeAccountAuthBusinessInfoEditBinding.bind(
View.inflate(
getContext(),
R.layout.view_life_account_auth_business_info_edit,
this
)
)
private var callback: OnLifeAccountAuthBusinessInfoEditViewCallback? = null
/**
* 是否输入错误标识位
*/
private var isInputError = false
init {
val typedArray =
context.obtainStyledAttributes(attrs, R.styleable.LifeAccountAuthBusinessInfoEditView)
viewBinding.tvContent.text =
typedArray.getText(R.styleable.LifeAccountAuthBusinessInfoEditView_LifeAccountAuthBusinessInfoEditView_content_text)
viewBinding.etContent.hint =
typedArray.getText(R.styleable.LifeAccountAuthBusinessInfoEditView_LifeAccountAuthBusinessInfoEditView_hint_text)
typedArray.recycle()
viewBinding.ivClear.setOnClickListener(this)
viewBinding.etContent.addTextChangedListener(this)
}
/**
* 展示错误提示
*/
fun showErrorTips(tips: String) {
viewBinding.tvErrorTips.isVisible = true
viewBinding.tvErrorTips.text = tips
}
/**
* 隐藏错误提示
*/
private fun dismissErrorTips() {
viewBinding.tvErrorTips.isVisible = false
viewBinding.tvErrorTips.text = ""
}
/**
* 清除输入的文字
*/
fun clearEditContent() {
viewBinding.etContent.setText("")
if (isInputError) {
dismissErrorTips()
cancelHighLightEditContent()
}
/**
* 展示错误提示
*/
fun showErrorTips(tips: String) {
viewBinding.tvErrorTips.isVisible = true
viewBinding.tvErrorTips.text = tips
callback?.onTextClear(this)
}
/**
* 填充传入的文字
*/
fun fillEditContent(content: String?) {
if (!TextUtils.isEmpty(content)) {
viewBinding.etContent.setText(content)
viewBinding.ivClear.visibility = View.VISIBLE
}
/**
* 隐藏错误提示
*/
private fun dismissErrorTips() {
viewBinding.tvErrorTips.isVisible = false
viewBinding.tvErrorTips.text = ""
}
/**
* 禁止修改
*/
fun disableModify() {
viewBinding.ivClear.isVisible = false
viewBinding.etContent.keyListener = null
}
/**
* 高亮显示输入文本
*/
fun highLightEditContent() {
isInputError = true
viewBinding.etContent.setTextColor(Color.parseColor("#FFFF3A3A"))
}
/**
* 取消高亮显示输入文本
*/
private fun cancelHighLightEditContent() {
isInputError = false
viewBinding.etContent.setTextColor(Color.parseColor("#FF333333"))
}
/**
* 设置输入过滤
*/
fun setInputFilters(vararg filter: InputFilter) {
viewBinding.etContent.filters = filter
}
override fun onClick(v: View?) {
if (v?.id == R.id.iv_clear) {
// 清除输入框中的内容
clearEditContent()
}
}
/**
* 清除输入的文字
*/
fun clearEditContent() {
viewBinding.etContent.setText("")
if (isInputError) {
dismissErrorTips()
cancelHighLightEditContent()
}
callback?.onTextClear(this)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
/**
* 填充传入的文字
*/
fun fillEditContent(content: String?) {
if (!TextUtils.isEmpty(content)) {
viewBinding.etContent.setText(content)
viewBinding.ivClear.visibility = View.VISIBLE
}
}
}
/**
* 禁止修改
*/
fun disableModify() {
viewBinding.ivClear.isVisible = false
viewBinding.etContent.keyListener = null
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
// 处理一键清除按钮
viewBinding.ivClear.isVisible = !TextUtils.isEmpty(s)
callback?.onTextChange(this, s.toString())
if (isInputError) {
dismissErrorTips()
cancelHighLightEditContent()
}
}
fun setOnLifeAccountAuthBusinessInfoEditViewCallback(callback: OnLifeAccountAuthBusinessInfoEditViewCallback) {
this.callback = callback
}
interface OnLifeAccountAuthBusinessInfoEditViewCallback {
/**
* 高亮显示输入文本
* 清除内容
*/
fun highLightEditContent() {
isInputError = true
viewBinding.etContent.setTextColor(Color.parseColor("#FFFF3A3A"))
}
fun onTextClear(from: LifeAccountAuthBusinessInfoEditView)
/**
* 取消高亮显示输入文本
* 内容修改
*/
private fun cancelHighLightEditContent() {
isInputError = false
viewBinding.etContent.setTextColor(Color.parseColor("#FF333333"))
}
override fun onClick(v: View?) {
if (v?.id == R.id.iv_clear) {
// 清除输入框中的内容
clearEditContent()
}
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(s: Editable?) {
// 处理一键清除按钮
viewBinding.ivClear.isVisible = !TextUtils.isEmpty(s)
callback?.onTextChange(this, s.toString())
if (isInputError) {
dismissErrorTips()
cancelHighLightEditContent()
}
}
fun setOnLifeAccountAuthBusinessInfoEditViewCallback(callback: OnLifeAccountAuthBusinessInfoEditViewCallback) {
this.callback = callback
}
interface OnLifeAccountAuthBusinessInfoEditViewCallback {
/**
* 清除内容
*/
fun onTextClear(from: LifeAccountAuthBusinessInfoEditView)
/**
* 内容修改
*/
fun onTextChange(from: LifeAccountAuthBusinessInfoEditView, text: String)
}
}
\ No newline at end of file
fun onTextChange(from: LifeAccountAuthBusinessInfoEditView, text: String)
}
}
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