Commit 1a402b85 authored by yinjiacheng's avatar yinjiacheng

update 认证流程

parent 963a89ff
......@@ -26,6 +26,7 @@ import com.yidian.common.XRouterPathConstants.Companion.PROTOCOL
import com.yidian.common.XRouterPathConstants.Companion.SUPPORT
import com.yidian.common.XRouterPathConstants.Companion.SYSTEM_SETTING
import com.yidian.common.YdBaseApplication
import com.yidian.news.YdImageLoader
import com.yidian.news.util.ProcessUtil
import com.yidian.nightmode.util.NightModeUtil
import com.yidian.shenghuoquan.newscontent.personnel.ui.*
......@@ -52,6 +53,7 @@ class NewsContentApplication : YdBaseApplication() {
initService()
NightModeUtil.setContext(this)
DensityUtil.init(this)
YdImageLoader.init(this)
}
}
......
......@@ -13,6 +13,7 @@ class LifeAccountMerchantAuthData {
var registrationCode: String = ""
var authRecordId: Long? = null
var lifeAccountId: Long? = null
var isRecoverAuthProcess: Boolean = false // 是否为恢复认证流程
// 营业执照相关信息
var type: String? = null
......
......@@ -6,10 +6,10 @@ package com.yidian.shenghuoquan.newscontent.bean
* description: 生活号个人认证数据集
*/
class LifeAccountPersonalAuthData {
var realName: String = ""
var idCardNum: String = ""
var phoneNum: String = "" // 法人手机号
var occupation: String = ""
var realName: String? = null
var idCardNum: String? = null
var phoneNum: String? = null // 法人手机号
var occupation: String? = null
var idCardPortraitFaceObjectKey: String? = null
var idCardNationalEmblemFaceObjectKey: String? = null
var idCardPortraitFaceBucket: String? = null
......
......@@ -57,4 +57,8 @@ object Constant {
const val DATA_FROM_C = 1 // C端
const val DATA_FROM_B = 2 // B端
const val DATA_FROM_OP = 3 // OP后台
// 服务端标识
const val ALIVE_DETECT_SUCCESS = 1 // 活体检测成功
const val ALIVE_DETECT_FAIL = 2 // 活体检测未检测或失败
}
\ No newline at end of file
......@@ -298,20 +298,20 @@ class ApiService {
}
// 103 认证完成后创建生活号
fun authComplete(apiCallback: IAuthCompleteCallback, requestParams: HashMap<String, String?>) {
fun authComplete(apiCallbackPersonal: IAuthPersonalCompleteCallback, requestParams: HashMap<String, String?>) {
val timeStamp = System.currentTimeMillis()
val publicParamsMap = HttpParamsUtils.getPublicParamsMap(timeStamp)
val privateParamsMap = HttpParamsUtils.getPrivateParamsMap(requestParams, timeStamp)
ServiceFactory.getInstance().createService(CommonService::class.java)
.authComplete(publicParamsMap, privateParamsMap)
.compose(TransformUtil.defaultSchedulers())
.subscribe(object : HttpResultSubscriber<Any?>() {
override fun onSuccess(result: HttpResult<Any?>?) {
apiCallback.authCompleteSuccess()
.subscribe(object : HttpResultSubscriber<AuthPersonalCompleteBean.Response?>() {
override fun onSuccess(result: HttpResult<AuthPersonalCompleteBean.Response?>?) {
apiCallbackPersonal.authPersonalCompleteSuccess(result?.result)
}
override fun onFailer(result: HttpResult<Any?>?) {
apiCallback.authCompleteFailure(result?.reason)
override fun onFailer(result: HttpResult<AuthPersonalCompleteBean.Response?>?) {
apiCallbackPersonal.authPersonalCompleteFailure(result?.reason)
}
})
}
......
package com.yidian.shenghuoquan.newscontent.http.callback
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthPersonalCompleteBean
/**
* author: yinjiacheng
* date: 6/1/21 7:43 PM
* description: API /merchant/auth/complete
*/
interface IAuthCompleteCallback {
fun authCompleteSuccess()
fun authCompleteFailure(message: String?)
interface IAuthPersonalCompleteCallback {
fun authPersonalCompleteSuccess(result: AuthPersonalCompleteBean.Response?)
fun authPersonalCompleteFailure(message: String?)
}
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.http.httpbean
import java.io.Serializable
/**
* author: yinjiacheng
* date: 6/1/21 7:54 PM
* description: API /merchant/auth/authentication
*/
class AuthAuthenticationBean(val response: Response) {
class AuthAuthenticationBean(val response: Response) : Serializable {
data class Response(
val audit_status: Int,
val back_id_card: String,
......@@ -14,6 +17,8 @@ class AuthAuthenticationBean(val response: Response) {
val full_name: String,
val id_card: String,
val live_identity_status: Int,
val occupation: String
)
val occupation: String,
val auth: Int
) : Serializable
}
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.http.httpbean
import java.io.Serializable
/**
* author: yinjiacheng
* date: 6/3/21 6:05 PM
* description: API /merchant/enterprise/check
*/
class AuthMerchantCheckBean {
class AuthMerchantCheckBean : Serializable{
data class Request(
val life_account_id: Long?,
......@@ -25,6 +27,6 @@ class AuthMerchantCheckBean {
val live_identity_status: Int,
val mobile: String,
val name: String
)
) : Serializable
}
\ No newline at end of file
......@@ -5,6 +5,7 @@ package com.yidian.shenghuoquan.newscontent.http.httpbean
* date: 6/1/21 7:40 PM
* description: API /merchant/auth/complete
*/
class AuthCompleteBean(val request: Request) {
data class Request(val mobile: String)
class AuthPersonalCompleteBean(val request: Request) {
data class Request(val mobile: String, val life_account_id: Long?)
data class Response(val life_account_id: Long)
}
\ No newline at end of file
......@@ -11,8 +11,7 @@ import com.yidian.shenghuoquan.newscontent.databinding.ActivityLifeAccountAuthBi
import com.yidian.shenghuoquan.newscontent.http.ApiService
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthAuthenticationCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthMerchantCheckCallback
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthAuthenticationBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthMerchantCheckBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.*
import com.yidian.xpage.XPageManager
/**
......@@ -78,11 +77,13 @@ class LifeAccountAuthActivity : BaseActivity<ActivityLifeAccountAuthBinding>(),
}
override fun authAuthenticationSuccess(result: AuthAuthenticationBean.Response?) {
// TODO: 6/6/21 带参跳转
viewBind.viewPersonalAuth.isSelected = true
viewBind.viewEnterpriseAuth.isSelected = false
// 跳转个人认证页
XPageManager.push(XRouterPathConstants.LIFE_ACCOUNT_PERSONAL_AUTH, null)
XPageManager.push(
XRouterPathConstants.LIFE_ACCOUNT_PERSONAL_AUTH,
hashMapOf(Pair(LifeAccountPersonalAuthActivity.EXTRA_AUTH_DATA, result))
)
}
override fun authAuthenticationFailure(message: String?) {
......@@ -90,18 +91,16 @@ class LifeAccountAuthActivity : BaseActivity<ActivityLifeAccountAuthBinding>(),
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth authentication failure, message: $message"
)
// Test
viewBind.viewPersonalAuth.isSelected = true
viewBind.viewEnterpriseAuth.isSelected = false
XPageManager.push(XRouterPathConstants.LIFE_ACCOUNT_PERSONAL_AUTH, null)
}
override fun authMerchantCheckSuccess(result: AuthMerchantCheckBean.Response?) {
// TODO: 6/6/21 带参跳转
viewBind.viewPersonalAuth.isSelected = false
viewBind.viewEnterpriseAuth.isSelected = true
// 跳转企业认证页
XPageManager.push(XRouterPathConstants.LIFE_ACCOUNT_ENTERPRISE_AUTH, null)
XPageManager.push(
XRouterPathConstants.LIFE_ACCOUNT_ENTERPRISE_AUTH,
hashMapOf(Pair(LifeAccountEnterpriseAuthActivity.EXTRA_AUTH_DATA, result))
)
}
override fun authMerchantCheckFailure(message: String?) {
......@@ -109,9 +108,5 @@ class LifeAccountAuthActivity : BaseActivity<ActivityLifeAccountAuthBinding>(),
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth merchant check failure, message: $message"
)
// Test
viewBind.viewPersonalAuth.isSelected = false
viewBind.viewEnterpriseAuth.isSelected = true
XPageManager.push(XRouterPathConstants.LIFE_ACCOUNT_ENTERPRISE_AUTH, null)
}
}
\ No newline at end of file
......@@ -100,7 +100,6 @@ object LifeAccountAuthDataManager {
* 生成营业执照上传接口请求体
*/
fun generateAuthBusinessLicenseCommitRequest(
dataType: Int,
lifeAccountId: Long?
): HashMap<String, String?> {
val requestMap = HashMap<String, String?>()
......@@ -121,7 +120,7 @@ object LifeAccountAuthDataManager {
requestMap["issue_date"] = merchantAuthData.date_issue
requestMap["entterprise_image"] = merchantAuthData.businessLicenseObjectKey
requestMap["data_from"] = Constant.DATA_FROM_B.toString()
requestMap["data_type"] = dataType.toString()
requestMap["data_type"] = merchantAuthData.merchantType.toString()
lifeAccountId?.let {
requestMap["life_account_id"] = it.toString()
}
......@@ -179,4 +178,16 @@ object LifeAccountAuthDataManager {
}
return requestMap
}
/**
* 生成个体工商户认证完成接口请求体
*/
fun generateAuthIndividualBusinessCompleteRequest(lifeAccountId: Long?): HashMap<String, String?> {
val requestMap = HashMap<String, String?>()
requestMap["record_id"] = merchantAuthData.authRecordId.toString()
lifeAccountId?.let {
requestMap["life_account_id"] = it.toString()
}
return requestMap
}
}
\ No newline at end of file
......@@ -12,6 +12,7 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.content.FileProvider
import androidx.core.view.isVisible
import com.bumptech.glide.Glide
import com.yidian.common.base.BaseFragment
import com.yidian.shenghuoquan.newscontent.R
import com.yidian.shenghuoquan.newscontent.adapter.BottomSelectAdapter
......@@ -19,6 +20,7 @@ import com.yidian.shenghuoquan.newscontent.bean.BottomSelectBean
import com.yidian.shenghuoquan.newscontent.constant.Constant
import com.yidian.shenghuoquan.newscontent.databinding.FragmentLifeAccountBusinessLicenseAuthBinding
import com.yidian.shenghuoquan.newscontent.http.ApiService
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthMerchantCheckBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.BusinessLicenseOCRBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.IBusinessLicenseOCRCallback
import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog
......@@ -39,6 +41,11 @@ class LifeAccountBusinessLicenseAuthFragment :
IBusinessLicenseOCRCallback,
LifeAccountAuthBusinessInfoEditView.OnLifeAccountAuthBusinessInfoEditViewCallback {
companion object {
// 认证数据
const val EXTRA_AUTH_DATA = "authData"
}
/**
* sdcard/Android/data/package/cache
*/
......@@ -60,6 +67,7 @@ class LifeAccountBusinessLicenseAuthFragment :
super.init(savedInstanceState)
initView()
initListener()
initData()
}
private fun initView() {
......@@ -74,6 +82,41 @@ class LifeAccountBusinessLicenseAuthFragment :
viewBinding.evRegistrationCode.setOnLifeAccountAuthBusinessInfoEditViewCallback(this)
}
private fun initData() {
// 还原认证数据
val authData =
arguments?.getSerializable(LifeAccountIDCardAuthFragment.EXTRA_AUTH_DATA) ?: return
fillAuthInfo(authData as AuthMerchantCheckBean.Response)
}
/**
* 认证流程中断,下次进入认证流程时还原进度
*/
private fun fillAuthInfo(data: AuthMerchantCheckBean.Response) {
LifeAccountAuthDataManager.merchantAuthData.registrationName = data.name
LifeAccountAuthDataManager.merchantAuthData.registrationCode = data.code
LifeAccountAuthDataManager.merchantAuthData.isBusinessLicenseUpload = true
// UI
Glide.with(this).load(data.entterprise_image).into(viewBinding.ivBusinessLicense)
// 填入注册名称和注册码
viewBinding.evRegistrationName.fillEditContent(data.name)
viewBinding.evRegistrationCode.fillEditContent(data.code)
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
lockAuthInfo()
}
/**
* 锁定当前输入状态
*/
private fun lockAuthInfo() {
viewBinding.ivClear.isVisible = false
viewBinding.clBusinessLicenseUpload.isEnabled = false
viewBinding.evRegistrationName.disableModify()
viewBinding.evRegistrationCode.disableModify()
(activity as LifeAccountEnterpriseAuthActivity).disableModifyMerchantType()
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.cl_business_license_upload -> {
......@@ -90,18 +133,7 @@ class LifeAccountBusinessLicenseAuthFragment :
}
}
R.id.iv_clear -> {
// 清除已上传的营业执照
viewBinding.ivBusinessLicense.setImageDrawable(null)
LifeAccountAuthDataManager.merchantAuthData.isBusinessLicenseUpload = false
// 清除OCR或用户输入内容
viewBinding.evRegistrationName.clearEditContent()
viewBinding.evRegistrationCode.clearEditContent()
LifeAccountAuthDataManager.merchantAuthData.registrationName = ""
LifeAccountAuthDataManager.merchantAuthData.registrationCode = ""
// 设置上传区域可点击
viewBinding.clBusinessLicenseUpload.isEnabled = true
// 隐藏清除按钮
viewBinding.ivClear.visibility = View.GONE
clearBusinessLicenseInfo()
// 检查下一步条件
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
......@@ -212,12 +244,18 @@ class LifeAccountBusinessLicenseAuthFragment :
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() {
......@@ -263,6 +301,10 @@ class LifeAccountBusinessLicenseAuthFragment :
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) {
......
......@@ -15,9 +15,7 @@ import com.yidian.shenghuoquan.newscontent.http.ApiService
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthBusinessLicenseCommitCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthIndividualBusinessCompleteCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthEnterpriseLegalIdentityCommitCallback
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthBusinessLicenseCommitBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthEnterpriseLegalIdentityCommitBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthIndividualBusinessCompleteBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.*
import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog
import com.yidian.shenghuoquan.newscontent.widget.LifeAccountAuthProcessView
import com.yidian.xpage.XPageManager
......@@ -33,10 +31,12 @@ class LifeAccountEnterpriseAuthActivity : BaseActivity<ActivityLifeAccountEnterp
IAuthIndividualBusinessCompleteCallback {
companion object {
/**
* 生活号id 个人生活号主动升级企业生活号的认证流程传入
*/
const val EXTRA_LIFE_ACCOUNT_ID = "life_account_id"
// 生活号id 个人生活号主动升级企业生活号的认证流程传入
const val EXTRA_LIFE_ACCOUNT_ID = "lifeAccountId"
// 认证数据
const val EXTRA_AUTH_DATA = "authData"
}
private val fragmentList: ArrayList<Fragment> by lazy {
......@@ -52,11 +52,24 @@ class LifeAccountEnterpriseAuthActivity : BaseActivity<ActivityLifeAccountEnterp
private var curFragment: Fragment? = null
/**
* 当前生活号id,个人生活号升级使用
* 个人生活号id 企业升级用
*/
private val personalLifeAccountId by lazy {
intent.getSerializableExtra(XRouterPathConstants.ParamsKey)?.let {
(it as HashMap<*, *>)[EXTRA_LIFE_ACCOUNT_ID]?.let { id ->
id as Long
}
}
}
/**
* 认证数据 还原认证流程用
*/
private val curLifeAccountId by lazy {
private val authData by lazy {
intent.getSerializableExtra(XRouterPathConstants.ParamsKey)?.let {
(it as HashMap<*, *>)[EXTRA_LIFE_ACCOUNT_ID] as Long
(it as HashMap<*, *>)[EXTRA_AUTH_DATA]?.let { data ->
data as AuthMerchantCheckBean.Response
}
}
}
......@@ -74,7 +87,7 @@ class LifeAccountEnterpriseAuthActivity : BaseActivity<ActivityLifeAccountEnterp
initListener()
// 默认企业资质Fragment
viewBind.pvAuthProcess.setProcess(LifeAccountAuthProcessView.PROCESS_ENTERPRISE_QUALIFICATION)
switchFragment(fragmentList[0])
initFragment()
}
private fun initView() {
......@@ -109,9 +122,9 @@ class LifeAccountEnterpriseAuthActivity : BaseActivity<ActivityLifeAccountEnterp
&& LifeAccountAuthDataManager.merchantAuthData.merchantType == Constant.TYPE_COMMON_ENTERPRISE
&& LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload
&& LifeAccountAuthDataManager.personalAuthData.isIDCardNationalEmblemFaceUpload
&& LifeAccountAuthDataManager.personalAuthData.realName.isNotEmpty()
&& LifeAccountAuthDataManager.personalAuthData.idCardNum.isNotEmpty()
&& LifeAccountAuthDataManager.personalAuthData.phoneNum.isNotEmpty()
&& !LifeAccountAuthDataManager.personalAuthData.realName.isNullOrEmpty()
&& !LifeAccountAuthDataManager.personalAuthData.idCardNum.isNullOrEmpty()
&& !LifeAccountAuthDataManager.personalAuthData.phoneNum.isNullOrEmpty()
) {
viewBind.btnNext.alpha = 1f
viewBind.btnNext.isEnabled = true
......@@ -121,6 +134,39 @@ class LifeAccountEnterpriseAuthActivity : BaseActivity<ActivityLifeAccountEnterp
}
}
/**
* 禁止修改商户类型
*/
fun disableModifyMerchantType() {
viewBind.svMerchantType.enableSelect(false)
}
private fun initFragment() {
if (authData == null) {
switchFragment(fragmentList[0])
} else {
// 如果有已存在的认证流程则还原进度
viewBind.svMerchantType.setContentResult(
if (authData?.data_type == Constant.TYPE_INDIVIDUAL_BUSINESS) {
Constant.ITEM_INDIVIDUAL_BUSINESSES
} else {
Constant.ITEM_COMMON_ENTERPRISE
}
)
LifeAccountAuthDataManager.merchantAuthData.merchantType =
if (authData?.data_type == Constant.TYPE_AUTH_INDIVIDUAL_BUSINESS) {
Constant.TYPE_INDIVIDUAL_BUSINESS
} else {
Constant.TYPE_COMMON_ENTERPRISE
}
val bundle = Bundle()
bundle.putSerializable(LifeAccountBusinessLicenseAuthFragment.EXTRA_AUTH_DATA, authData)
fragmentList[0].arguments = bundle
switchFragment(fragmentList[0])
LifeAccountAuthDataManager.merchantAuthData.isRecoverAuthProcess = true
}
}
/**
* fragment切换
*/
......@@ -179,30 +225,43 @@ class LifeAccountEnterpriseAuthActivity : BaseActivity<ActivityLifeAccountEnterp
}
R.id.btn_next -> {
if (viewBind.pvAuthProcess.curProcess == LifeAccountAuthProcessView.PROCESS_ENTERPRISE_QUALIFICATION) {
// TODO: 6/4/21 判断是否为个人生活号升级
// personalLifeAccountId不为null则是由个人生活号升级为企业生活号情况
// personalLifeAccountId为null则是直接进行企业认证情况
if (LifeAccountAuthDataManager.merchantAuthData.isRecoverAuthProcess) {
viewBind.pvAuthProcess.setProcess(++viewBind.pvAuthProcess.curProcess)
// 向身份信息fragment传参
val fragment = fragmentList[viewBind.pvAuthProcess.curProcess]
val bundle = Bundle()
bundle.putInt(
Constant.TYPE_AUTH,
LifeAccountAuthDataManager.merchantAuthData.merchantType
)
bundle.putSerializable(
LifeAccountIDCardAuthFragment.EXTRA_AUTH_DATA,
authData
)
fragment.arguments = bundle
switchFragment(fragment)
}
ApiService.authBusinessLicenseCommit(
this,
LifeAccountAuthDataManager.generateAuthBusinessLicenseCommitRequest(
LifeAccountAuthDataManager.merchantAuthData.merchantType,
curLifeAccountId
personalLifeAccountId
)
)
} else if (viewBind.pvAuthProcess.curProcess == LifeAccountAuthProcessView.PROCESS_ENTERPRISE_MANAGER) {
if (LifeAccountAuthDataManager.merchantAuthData.merchantType == Constant.TYPE_INDIVIDUAL_BUSINESS) {
ApiService.authIndividualBusinessComplete(
this,
hashMapOf(
Pair(
"record_id",
LifeAccountAuthDataManager.merchantAuthData.authRecordId.toString()
)
LifeAccountAuthDataManager.generateAuthIndividualBusinessCompleteRequest(
personalLifeAccountId
)
)
} else if (LifeAccountAuthDataManager.merchantAuthData.merchantType == Constant.TYPE_COMMON_ENTERPRISE) {
ApiService.authEnterpriseLegalIdentityCommit(
this,
LifeAccountAuthDataManager.generateAuthEnterpriseLegalIdentityCommitRequest(
curLifeAccountId
personalLifeAccountId
)
)
}
......@@ -237,9 +296,9 @@ class LifeAccountEnterpriseAuthActivity : BaseActivity<ActivityLifeAccountEnterp
Constant.TYPE_AUTH,
LifeAccountAuthDataManager.merchantAuthData.merchantType
)
bundle.putSerializable(LifeAccountIDCardAuthFragment.EXTRA_AUTH_DATA, authData)
fragment.arguments = bundle
switchFragment(fragment)
checkNextCondition()
}
override fun authBusinessLicenseCommitFailure(message: String?) {
......
package com.yidian.shenghuoquan.newscontent.ui.auth
import android.app.Activity
import android.content.ContentResolver
import android.content.Intent
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.FileUtils
import android.provider.MediaStore
import android.util.Log
import android.view.LayoutInflater
......@@ -23,7 +19,6 @@ import com.megvii.meglive_sdk.listener.PreCallback
import com.megvii.meglive_sdk.manager.MegLiveManager
import com.yidian.common.base.BaseFragment
import com.yidian.common.http.HttpResult
import com.yidian.common.utils.YdFileUtils
import com.yidian.shenghuoquan.newscontent.R
import com.yidian.shenghuoquan.newscontent.adapter.BottomSelectAdapter
import com.yidian.shenghuoquan.newscontent.bean.BottomSelectBean
......@@ -44,7 +39,6 @@ import com.yidian.shenghuoquan.newscontent.widget.LifeAccountAuthImageView
import com.yidian.shenghuoquan.newscontent.widget.LifeAccountFaceAuthView
import com.yidian.utils.ToastUtil
import java.io.File
import java.io.FileOutputStream
/**
* author: yinjiacheng
......@@ -72,6 +66,9 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
//活体检测请求host 详见文档
private const val ALIVE_DETECT_HOST = "https://api.megvii.com"
// 认证数据
const val EXTRA_AUTH_DATA = "authData"
}
/**
......@@ -118,11 +115,13 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
super.init(savedInstanceState)
initView()
initListener()
initData()
initFaceID()
}
private fun initView() {
authType = arguments?.getInt(Constant.TYPE_AUTH, -1) ?: Constant.TYPE_AUTH_PERSONAL
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))
......@@ -150,6 +149,12 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
viewBinding.avFaceAuth.setOnLifeAccountFaceAuthCallback(this)
}
private fun initData() {
// 还原认证数据
val authData = arguments?.getSerializable(EXTRA_AUTH_DATA) ?: return
fillAuthInfo(authData as AuthAuthenticationBean.Response)
}
/**
* 初始化旷视FaceID
*/
......@@ -194,6 +199,43 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
return false
}
/**
* 认证流程中断,下次进入认证流程时还原进度
*/
private fun fillAuthInfo(data: AuthAuthenticationBean.Response) {
// 保存姓名和身份证号 用于后面进行人脸验证
LifeAccountAuthDataManager.personalAuthData.realName = data.full_name
LifeAccountAuthDataManager.personalAuthData.idCardNum = data.id_card
LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass =
data.live_identity_status == Constant.ALIVE_DETECT_SUCCESS
// UI
activity?.let { viewBinding.ivIdCardPortraitFace.addImage(it, data.front_id_card) }
activity?.let { viewBinding.ivIdCardNationalEmblemFace.addImage(it, data.back_id_card) }
viewBinding.evRealName.fillEditContent(data.full_name)
viewBinding.evIdCardNumber.fillEditContent(data.id_card)
viewBinding.avFaceAuth.showFaceAuthResult(data.live_identity_status == Constant.ALIVE_DETECT_SUCCESS)
// 如果人脸验证已通过 则直接锁定输入状态
if (data.live_identity_status == Constant.ALIVE_DETECT_SUCCESS) lockAuthInfo()
// 检查下一步条件
if (authType == Constant.TYPE_AUTH_PERSONAL) {
(activity as LifeAccountPersonalAuthActivity).checkNextCondition()
} else {
(activity as LifeAccountEnterpriseAuthActivity).checkNextCondition()
}
}
/**
* 锁定当前输入状态
* 即完成人脸验证后无法修改身份证照片、姓名、身份证号、职业标签
*/
private fun lockAuthInfo() {
viewBinding.ivIdCardPortraitFace.disableModify()
viewBinding.ivIdCardNationalEmblemFace.disableModify()
viewBinding.evRealName.disableModify()
viewBinding.evIdCardNumber.disableModify()
(activity as LifeAccountPersonalAuthActivity).disableModifyOccupation()
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.iv_id_card_portrait_face -> {
......@@ -479,11 +521,7 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
File(cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA).apply {
if (exists()) delete()
}
// 锁定当前输入状态 即完成人脸验证后无法修改身份证照片、姓名、身份证号
viewBinding.ivIdCardPortraitFace.disableModify()
viewBinding.ivIdCardNationalEmblemFace.disableModify()
viewBinding.evRealName.disableModify()
viewBinding.evIdCardNumber.disableModify()
lockAuthInfo()
// 回调server 保存活体识别认证状态
if (authType == Constant.TYPE_AUTH_PERSONAL) {
ApiService.authLiveIdentity(this)
......@@ -599,11 +637,14 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
if (exists()) delete()
}
// 跳转人脸认证
val requestParams = HashMap<String, String?>()
requestParams["id_number"] = LifeAccountAuthDataManager.personalAuthData.idCardNum
requestParams["id_card_name"] = LifeAccountAuthDataManager.personalAuthData.realName
requestParams["liveness_type"] = Constant.TYPE_MEG_LIVE
ApiService.authPersonalGetToken(this, requestParams)
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?) {
......@@ -704,7 +745,10 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
override fun onStartFaceAuth() {
// 判断是否满足条件进行活体检测
if (!checkFaceAuthCondition()) return
if (!checkFaceAuthCondition()) {
ToastUtil.showToast(activity, "请补全信息后重试")
return
}
when (authType) {
Constant.TYPE_AUTH_PERSONAL -> {
ApiService.authPersonalCheck(
......@@ -728,11 +772,14 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
if (exists()) delete()
}
// 跳转人脸认证
val requestParams = HashMap<String, String?>()
requestParams["id_number"] = LifeAccountAuthDataManager.personalAuthData.idCardNum
requestParams["id_card_name"] = LifeAccountAuthDataManager.personalAuthData.realName
requestParams["liveness_type"] = Constant.TYPE_MEG_LIVE
ApiService.authPersonalGetToken(this, requestParams)
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?) {
......@@ -755,41 +802,20 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
/**
* 本地校验是否可以进行人脸验证
* 必须同时满足真实姓名已填、身份证号已填、身份证两面已上传、职业标签已选
* 必须同时满足真实姓名已填、身份证号已填、身份证两面已上传、职业标签已选(只有个人认证需要)
*/
private fun checkFaceAuthCondition(): Boolean {
// TODO: 6/2/21 添加职业标签校验
return LifeAccountAuthDataManager.personalAuthData.realName.isNotEmpty()
&& LifeAccountAuthDataManager.personalAuthData.idCardNum.isNotEmpty()
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
}
/**
* 通过Uri获取文件全路径
* 适配Android Q
*/
@Deprecated("Temporary")
private fun getFilePathFromUri(uri: Uri?, path: String): String? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val file = File(path)
if (file.exists()) {
file.delete()
}
file.parentFile?.mkdirs()
file.createNewFile()
if (uri?.scheme == ContentResolver.SCHEME_CONTENT) {
val inputStream = activity?.contentResolver?.openInputStream(uri)
val fileOutputStream = FileOutputStream(file)
inputStream?.let { FileUtils.copy(it, fileOutputStream) }
inputStream?.close()
fileOutputStream.close()
return file.absolutePath
}
return null
} else {
return YdFileUtils.getImageAbsolutePath(activity, uri)
}
return !LifeAccountAuthDataManager.personalAuthData.realName.isNullOrEmpty()
&& !LifeAccountAuthDataManager.personalAuthData.idCardNum.isNullOrEmpty()
&& LifeAccountAuthDataManager.personalAuthData.isIDCardPortraitFaceUpload
&& LifeAccountAuthDataManager.personalAuthData.isIDCardNationalEmblemFaceUpload
}
}
......@@ -12,7 +12,9 @@ import com.yidian.shenghuoquan.newscontent.R
import com.yidian.shenghuoquan.newscontent.constant.Constant
import com.yidian.shenghuoquan.newscontent.databinding.ActivityLifeAccountPersonalAuthBinding
import com.yidian.shenghuoquan.newscontent.http.ApiService
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthCompleteCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthPersonalCompleteCallback
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthAuthenticationBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthPersonalCompleteBean
import com.yidian.xpage.XPageManager
/**
......@@ -20,8 +22,19 @@ import com.yidian.xpage.XPageManager
* date: 5/26/21 7:38 PM
* description: 生活号个人认证
*/
class LifeAccountPersonalAuthActivity : BaseActivity<ActivityLifeAccountPersonalAuthBinding>(),
View.OnClickListener, CompoundButton.OnCheckedChangeListener, IAuthCompleteCallback {
class LifeAccountPersonalAuthActivity :
BaseActivity<ActivityLifeAccountPersonalAuthBinding>(),
View.OnClickListener, CompoundButton.OnCheckedChangeListener, IAuthPersonalCompleteCallback {
companion object {
// 认证数据
const val EXTRA_AUTH_DATA = "authData"
}
/**
* 当前fragment
*/
private val fragment by lazy { LifeAccountIDCardAuthFragment() }
override fun createViewBinding(): ActivityLifeAccountPersonalAuthBinding {
return ActivityLifeAccountPersonalAuthBinding.inflate(layoutInflater)
......@@ -33,10 +46,9 @@ class LifeAccountPersonalAuthActivity : BaseActivity<ActivityLifeAccountPersonal
override fun init(savedInstanceState: Bundle?) {
super.init(savedInstanceState)
supportFragmentManager.beginTransaction()
.add(R.id.fragment_container, LifeAccountIDCardAuthFragment()).commit()
initView()
initListener()
initFragment()
}
private fun initView() {
......@@ -50,12 +62,30 @@ class LifeAccountPersonalAuthActivity : BaseActivity<ActivityLifeAccountPersonal
viewBind.btnNext.setOnClickListener(this)
}
private fun initFragment() {
val authData = intent.getSerializableExtra(XRouterPathConstants.ParamsKey)?.let {
(it as HashMap<*, *>)[EXTRA_AUTH_DATA]?.let { data ->
data as AuthAuthenticationBean.Response
}
}
// 如果有已存在的认证流程则还原进度
val bundle = Bundle()
bundle.putSerializable(LifeAccountIDCardAuthFragment.EXTRA_AUTH_DATA, authData)
fragment.arguments = bundle
supportFragmentManager.beginTransaction()
.add(R.id.fragment_container, fragment).commit()
authData?.occupation?.let {
viewBind.svOccupation.setContentResult(it)
LifeAccountAuthDataManager.personalAuthData.occupation = it
}
}
/**
* 检查是否可以进行下一步
*/
fun checkNextCondition() {
if (viewBind.cbProtocol.isChecked
&& LifeAccountAuthDataManager.personalAuthData.occupation.isNotEmpty()
&& !LifeAccountAuthDataManager.personalAuthData.occupation.isNullOrEmpty()
&& LifeAccountAuthDataManager.personalAuthData.isFaceAuthPass
) {
viewBind.btnNext.alpha = 1f
......@@ -66,6 +96,13 @@ class LifeAccountPersonalAuthActivity : BaseActivity<ActivityLifeAccountPersonal
}
}
/**
* 禁止修改职业标签 用于人脸验证通过后
*/
fun disableModifyOccupation() {
viewBind.svOccupation.enableSelect(false)
}
override fun onClick(v: View?) {
when (v?.id) {
R.id.iv_back -> XPageManager.pop(null)
......@@ -73,6 +110,7 @@ class LifeAccountPersonalAuthActivity : BaseActivity<ActivityLifeAccountPersonal
// TODO: 5/27/21 跳转职业标签选择 选择完成后进行下一步检查
LifeAccountAuthDataManager.personalAuthData.occupation = "工程师"
viewBind.svOccupation.setContentResult("工程师")
checkNextCondition()
}
R.id.btn_next -> {
// 个人认证 完成认证
......@@ -91,11 +129,36 @@ class LifeAccountPersonalAuthActivity : BaseActivity<ActivityLifeAccountPersonal
checkNextCondition()
}
override fun authCompleteSuccess() {
// TODO: 6/3/21 跳转个人认证成功页
override fun authPersonalCompleteSuccess(result: AuthPersonalCompleteBean.Response?) {
// 跳转个人认证成功页
XPageManager.push(
XRouterPathConstants.LIFE_ACCOUNT_PERSONAL_AUTH_COMPLETE,
hashMapOf(
Pair(
LifeAccountPersonalAuthCompleteActivity.OCCUPATION,
LifeAccountAuthDataManager.personalAuthData.occupation
),
Pair(
LifeAccountPersonalAuthCompleteActivity.PHONE_NUM,
Hawk.get(HawkConfig.Mobile, "")
),
Pair(
LifeAccountPersonalAuthCompleteActivity.REAL_NAME,
LifeAccountAuthDataManager.personalAuthData.realName
),
Pair(
LifeAccountPersonalAuthCompleteActivity.ID_CARD_NUM,
LifeAccountAuthDataManager.personalAuthData.idCardNum
),
Pair(
LifeAccountPersonalAuthCompleteActivity.LIFE_ACCOUNT_ID,
result?.life_account_id
)
)
)
}
override fun authCompleteFailure(message: String?) {
override fun authPersonalCompleteFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth complete failure: message: $message"
......
......@@ -21,6 +21,7 @@ class LifeAccountPersonalAuthCompleteActivity :
const val REAL_NAME = "realName"
const val ID_CARD_NUM = "idCardNum"
const val PHONE_NUM = "phoneNum"
const val LIFE_ACCOUNT_ID = "lifeAccountId" // 个人生活号升级用
}
/**
......@@ -57,10 +58,22 @@ class LifeAccountPersonalAuthCompleteActivity :
private fun initListener() {
viewBind.enterLifeAccount.setOnClickListener {
// TODO: 2021/5/27 跳转生活号管理首页
// 跳转生活号管理首页
XPageManager.push(XRouterPathConstants.MERCHANT_CENTER, null)
finish()
}
viewBind.upgradeEnterpriseAuth.setOnClickListener {
XPageManager.push(XRouterPathConstants.LIFE_ACCOUNT_ENTERPRISE_AUTH, null)
// TODO: 6/10/21 传入生活号id
XPageManager.push(
XRouterPathConstants.LIFE_ACCOUNT_ENTERPRISE_AUTH,
hashMapOf(
Pair(
LifeAccountEnterpriseAuthActivity.EXTRA_LIFE_ACCOUNT_ID,
params[LIFE_ACCOUNT_ID] as Long
)
)
)
finish()
}
}
}
\ No newline at end of file
......@@ -94,7 +94,7 @@ class LifeAccountAuthBusinessInfoEditView @JvmOverloads constructor(
*/
fun disableModify() {
viewBinding.ivClear.isVisible = false
isEnabled = false
viewBinding.etContent.keyListener = null
}
/**
......
......@@ -100,7 +100,7 @@ class LifeAccountAuthIdentityInfoEditView @JvmOverloads constructor(
*/
fun disableModify() {
viewBinding.ivClear.visibility = View.GONE
isEnabled = false
viewBinding.etContent.keyListener = null
}
/**
......
......@@ -5,6 +5,7 @@ import android.graphics.Bitmap
import android.util.AttributeSet
import android.view.View
import androidx.core.view.isVisible
import com.bumptech.glide.Glide
import com.yidian.nightmode.widget.YdConstraintLayout
import com.yidian.shenghuoquan.newscontent.R
import com.yidian.shenghuoquan.newscontent.databinding.ViewLifeAccountAuthImageBinding
......@@ -63,6 +64,16 @@ class LifeAccountAuthImageView @JvmOverloads constructor(
viewBinding.ivClear.isVisible = true
}
/**
* 填充图片
* @param url 图片url
*/
fun addImage(context: Context, url: String) {
Glide.with(context).load(url).into(viewBinding.ivContent)
isEnabled = false
viewBinding.ivClear.isVisible = true
}
/**
* 清除图片
*/
......
......@@ -57,6 +57,7 @@
android:layout_marginBottom="33dp"
android:alpha="0.32"
android:background="@drawable/bg_btn_auth"
android:enabled="false"
android:gravity="center"
android:text="@string/next_step"
android:textColor="#FFFFFFFF"
......
......@@ -81,6 +81,7 @@
android:layout_marginBottom="33dp"
android:alpha="0.32"
android:background="@drawable/bg_btn_auth"
android:enabled="false"
android:text="@string/auth_finish"
android:textColor="#FFFFFFFF"
android:textSize="17sp"
......
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