Commit ef82a071 authored by yinjiacheng's avatar yinjiacheng

add 个人认证流程相关接口

parent 7f18ade4
......@@ -6,8 +6,8 @@ class URLs {
companion object{
val BASE_URL: String
private const val BASE_URL_DEBUG = "http://bp-test.go2yd.com"
private const val BASE_URL_PRO = "http://bp-test.go2yd.com"
private const val BASE_URL_DEBUG = "http://bp-dev.go2yd.com"
private const val BASE_URL_PRO = "http://bp-dev.go2yd.com"
init {
BASE_URL = if (BuildConfig.ENV_DEBUG){
......@@ -33,5 +33,9 @@ class URLs {
const val mobileLogin = "/user/user/login"
const val accountList = "/merchant/auth/account_list"
const val createLifeAccount = "/merchant/enterprise/create_life"
const val authPersonalCheck = "/merchant/auth/personal_check"
const val authLiveIdentity = "/merchant/auth/live_identity"
const val authComplete = "/merchant/auth/complete"
const val authAuthentication = "/merchant/auth/authentication"
}
}
\ No newline at end of file
......@@ -12,4 +12,13 @@ class LifeAccountPersonalAuthData {
var idCardNationalEmblemFaceObjectKey: String = ""
var liveDetectBizToken: String = ""
var liveDetectObjectKey: String = ""
var idCardPortraitFaceCompleteness: Int = -1
var idCardNationalEmblemFaceCompleteness: Int = -1
var gender: String = ""
var occupation: String = "工程师"
var address: String = ""
var nationality: String = ""
var validDateStart: String = ""
var validDateEnd: String = ""
var issuedBy: String = ""
}
......@@ -7,6 +7,10 @@ import com.yidian.common.http.TransformUtil
import com.yidian.http.ServiceFactory
import com.yidian.shenghuoquan.newscontent.bean.CreateLifeAccountBean
import com.yidian.shenghuoquan.newscontent.bean.ICreateLifeAccountCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthAuthenticationCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthCompleteCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthLiveIdentityCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthPersonalCheckCallback
import com.yidian.shenghuoquan.newscontent.http.httpbean.*
import okhttp3.MultipartBody
......@@ -225,5 +229,73 @@ class ApiService {
}
})
}
// 101 身份信息校验接口
fun authPersonalCheck(apiCallback: IAuthPersonalCheckCallback, requestParams: AuthPersonalCheckBean.Request) {
val paramsMap = HttpParamsUtils.getParamsMap()
ServiceFactory.getInstance().createService(CommonService::class.java)
.authPersonalCheck(paramsMap, requestParams)
.compose(TransformUtil.defaultSchedulers())
.subscribe(object : HttpResultSubscriber<Any>() {
override fun onSuccess(result: HttpResult<Any>?) {
apiCallback.authPersonCheckSuccess()
}
override fun onFailer(result: HttpResult<Any>?) {
apiCallback.authPersonCheckFailure(result?.reason)
}
})
}
// 102 活体识别成功后回调接口
fun authLiveIdentity(apiCallback: IAuthLiveIdentityCallback) {
val paramsMap = HttpParamsUtils.getParamsMap()
ServiceFactory.getInstance().createService(CommonService::class.java)
.authLiveIdentity(paramsMap)
.compose(TransformUtil.defaultSchedulers())
.subscribe(object : HttpResultSubscriber<Any>() {
override fun onSuccess(result: HttpResult<Any>?) {
apiCallback.authLiveIdentitySuccess()
}
override fun onFailer(result: HttpResult<Any>?) {
apiCallback.authLiveIdentityFailure(result?.reason)
}
})
}
// 103 认证完成后创建生活号
fun authComplete(apiCallback: IAuthCompleteCallback, requestParams: AuthCompleteBean.Request) {
val paramsMap = HttpParamsUtils.getParamsMap()
ServiceFactory.getInstance().createService(CommonService::class.java)
.authComplete(paramsMap, requestParams)
.compose(TransformUtil.defaultSchedulers())
.subscribe(object : HttpResultSubscriber<Any>() {
override fun onSuccess(result: HttpResult<Any>?) {
apiCallback.authCompleteSuccess()
}
override fun onFailer(result: HttpResult<Any>?) {
apiCallback.authCompleteFailure(result?.reason)
}
})
}
// 104 检测是否可以个人认证,返回认证信息
fun authAuthentication(apiCallback: IAuthAuthenticationCallback) {
val paramsMap = HttpParamsUtils.getParamsMap()
ServiceFactory.getInstance().createService(CommonService::class.java)
.authAuthentication(paramsMap)
.compose(TransformUtil.defaultSchedulers())
.subscribe(object : HttpResultSubscriber<AuthAuthenticationBean.Response>() {
override fun onSuccess(result: HttpResult<AuthAuthenticationBean.Response>?) {
apiCallback.authAuthenticationSuccess(result?.result)
}
override fun onFailer(result: HttpResult<AuthAuthenticationBean.Response>?) {
apiCallback.authAuthenticationFailure(result?.reason)
}
})
}
}
}
......@@ -59,4 +59,17 @@ interface CommonService {
@Headers("Content-Type: application/json")
@POST(URLs.createLifeAccount)
fun createLifeAccount(@QueryMap commonParams: Map<String, String>,@Body requestParams: CreateLifeAccountBean.Request) :Observable<HttpResult<Any?>>
@Headers("Content-Type: application/json")
@POST(URLs.authPersonalCheck)
fun authPersonalCheck(@QueryMap commonParams: Map<String, String>, @Body requestParams: AuthPersonalCheckBean.Request) : Observable<HttpResult<Any>>
@GET(URLs.authLiveIdentity)
fun authLiveIdentity(@QueryMap commonParams: Map<String, String>): Observable<HttpResult<Any>>
@GET(URLs.authComplete)
fun authComplete(@QueryMap commonParams: Map<String, String>, @QueryMap requestParams: AuthCompleteBean.Request): Observable<HttpResult<Any>>
@GET(URLs.authAuthentication)
fun authAuthentication(@QueryMap commonParams: Map<String, String>): Observable<HttpResult<AuthAuthenticationBean.Response>>
}
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.http.callback
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthAuthenticationBean
/**
* author: yinjiacheng
* date: 6/1/21 8:13 PM
* description: API /merchant/auth/authentication
*/
interface IAuthAuthenticationCallback {
fun authAuthenticationSuccess(result: AuthAuthenticationBean.Response?)
fun authAuthenticationFailure(message: String?)
}
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.http.callback
/**
* author: yinjiacheng
* date: 6/1/21 7:43 PM
* description: API /merchant/auth/complete
*/
interface IAuthCompleteCallback {
fun authCompleteSuccess()
fun authCompleteFailure(message: String?)
}
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.http.callback
/**
* author: yinjiacheng
* date: 6/1/21 7:52 PM
* description: API /merchant/auth/live_identity
*/
interface IAuthLiveIdentityCallback {
fun authLiveIdentitySuccess()
fun authLiveIdentityFailure(message: String?)
}
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.http.callback
/**
* author: yinjiacheng
* date: 6/1/21 5:50 PM
* description: API /merchant/auth/personal_check
*/
interface IAuthPersonalCheckCallback {
fun authPersonCheckSuccess()
fun authPersonCheckFailure(message: String?)
}
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.http.httpbean
/**
* author: yinjiacheng
* date: 6/1/21 7:54 PM
* description: API /merchant/auth/authentication
*/
class AuthAuthenticationBean(val response: Response) {
data class Response(
val audit_status: Int,
val back_id_card: String,
val create_time: String,
val front_id_card: String,
val full_name: String,
val id_card: String,
val live_identity_status: Int,
val occupation: String
)
}
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.http.httpbean
/**
* author: yinjiacheng
* date: 6/1/21 7:40 PM
* description: API /merchant/auth/complete
*/
class AuthCompleteBean(val request: Request) {
data class Request(val mobile: String)
}
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.http.httpbean
/**
* author: yinjiacheng
* date: 6/1/21 5:46 PM
* description: API /merchant/auth/personal_check
*/
class AuthPersonalCheckBean(val request: Request) {
data class Request(
val front_img: String,
val bak_img: String,
val front_completeness: Int,
val bak_completeness: Int,
val id_card: String,
val gender: String,
val name: String,
val occupation: String,
val address: String,
val nationality: String,
val valid_date_start: String,
val valid_date_end: String,
val issued_by: String
)
}
\ No newline at end of file
package com.yidian.shenghuoquan.newscontent.ui.auth
import com.yidian.shenghuoquan.newscontent.bean.LifeAccountPersonalAuthData
import com.yidian.shenghuoquan.newscontent.http.httpbean.AuthPersonalCheckBean
import com.yidian.shenghuoquan.newscontent.http.httpbean.GetIDCardOCRBean
/**
* author: yinjiacheng
......@@ -8,5 +10,43 @@ import com.yidian.shenghuoquan.newscontent.bean.LifeAccountPersonalAuthData
* description: 生活号认证数据管理
*/
object LifeAccountAuthDataManager {
val personalAuthData by lazy { LifeAccountPersonalAuthData() }
/**
* 将身份证OCR结果填入
*/
fun generatePersonalAuthData(data: GetIDCardOCRBean.Response) {
personalAuthData.idCardPortraitFaceCompleteness = data.posit.completeness
personalAuthData.idCardNationalEmblemFaceCompleteness = data.posit.completeness
personalAuthData.idCardNum = data.posit.idcard_number
personalAuthData.gender = data.posit.gender
personalAuthData.realName = data.posit.name
personalAuthData.address = data.posit.address
personalAuthData.nationality = data.posit.nationality
personalAuthData.validDateStart = data.back.valid_date_start
personalAuthData.validDateEnd = data.back.valid_date_end
personalAuthData.issuedBy = data.back.issued_by
}
/**
* 使用个人认证数据生成身份信息校验接口请求体
*/
fun generateAuthPersonalCheckRequest(): AuthPersonalCheckBean.Request {
return AuthPersonalCheckBean.Request(
personalAuthData.idCardPortraitFaceObjectKey,
personalAuthData.idCardNationalEmblemFaceObjectKey,
personalAuthData.idCardPortraitFaceCompleteness,
personalAuthData.idCardNationalEmblemFaceCompleteness,
personalAuthData.idCardNum,
personalAuthData.gender,
personalAuthData.realName,
personalAuthData.occupation,
personalAuthData.address,
personalAuthData.nationality,
personalAuthData.validDateStart,
personalAuthData.validDateEnd,
personalAuthData.issuedBy
)
}
}
\ No newline at end of file
......@@ -30,6 +30,8 @@ import com.yidian.shenghuoquan.newscontent.bean.BottomSelectBean
import com.yidian.shenghuoquan.newscontent.constant.Constant
import com.yidian.shenghuoquan.newscontent.databinding.FragmentLifeAccountIdCardAuthBinding
import com.yidian.shenghuoquan.newscontent.http.ApiService
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthLiveIdentityCallback
import com.yidian.shenghuoquan.newscontent.http.callback.IAuthPersonalCheckCallback
import com.yidian.shenghuoquan.newscontent.http.httpbean.*
import com.yidian.shenghuoquan.newscontent.ui.dialog.BottomSelectDialog
import com.yidian.shenghuoquan.newscontent.utils.BitmapUtil
......@@ -47,7 +49,8 @@ import java.io.FileOutputStream
class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuthBinding>(),
View.OnClickListener, BottomSelectAdapter.OnItemClickListener<BottomSelectBean>,
IGetIDCardOCRCallback, AuthPersonalGetTokenCallback, IdentifyIdOcrVerifyCallback, PreCallback,
DetectCallback, KS3Core.OnKS3TaskListener {
DetectCallback, KS3Core.OnKS3TaskListener, IAuthPersonalCheckCallback,
IAuthLiveIdentityCallback {
companion object {
// 身份证采集页面回传数据
......@@ -184,15 +187,11 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
}
}
R.id.iv_face_auth_start -> {
// 若存在上一次活体检测数据则删除 处理活体检测失败 再次进入
File(cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA).delete()
// 跳转人脸认证
ApiService.authPersonalGetToken(
this, AuthPersonalGetTokenBean.Request(
LifeAccountAuthDataManager.personalAuthData.idCardNum,
LifeAccountAuthDataManager.personalAuthData.realName,
Constant.TYPE_MEG_LIVE
)
// 判断是否满足条件进行活体检测
if (!checkFaceAuthCondition()) return
ApiService.authPersonalCheck(
this,
LifeAccountAuthDataManager.generateAuthPersonalCheckRequest()
)
}
}
......@@ -403,12 +402,7 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
override fun getIDCardOCRSuccess(result: GetIDCardOCRBean.Response?) {
// 存储认证使用的信息
result?.posit?.name?.let {
LifeAccountAuthDataManager.personalAuthData.realName = it
}
result?.posit?.idcard_number?.let {
LifeAccountAuthDataManager.personalAuthData.idCardNum = it
}
result?.let { LifeAccountAuthDataManager.generatePersonalAuthData(it) }
// 回显OCR结果
viewBinding.evRealName.fillEditContent(result?.posit?.name)
viewBinding.evIdCardNumber.fillEditContent(result?.posit?.idcard_number)
......@@ -445,6 +439,8 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
changeFaceAuthUI(true)
// 删除活体检测数据
File(cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA).delete()
// 回调server 保存活体识别认证状态
ApiService.authLiveIdentity(this)
}
}
......@@ -532,6 +528,38 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
)
}
override fun authPersonCheckSuccess() {
// 身份信息校验成功后才允许进行人脸验证
// 若存在上一次活体检测数据则删除 处理活体检测失败 再次进入
File(cachePath + Constant.FILE_PATH_ALIVE_DETECT_VERIFY_DATA).delete()
// 跳转人脸认证
ApiService.authPersonalGetToken(
this, AuthPersonalGetTokenBean.Request(
LifeAccountAuthDataManager.personalAuthData.idCardNum,
LifeAccountAuthDataManager.personalAuthData.realName,
Constant.TYPE_MEG_LIVE
)
)
}
override fun authPersonCheckFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth personal check failure: message: $message"
)
}
override fun authLiveIdentitySuccess() {
}
override fun authLiveIdentityFailure(message: String?) {
Log.e(
Constant.LIFE_ACCOUNT_AUTH_TAG,
"request auth live identity failure: message: $message"
)
}
/**
* 人脸验证结果UI
* @param result true为验证通过 false为验证未通过
......@@ -550,6 +578,18 @@ class LifeAccountIDCardAuthFragment : BaseFragment<FragmentLifeAccountIdCardAuth
}
}
/**
* 本地校验是否可以进行人脸验证
* 必须同时满足真实姓名已填、身份证号已填、身份证两面已上传
*/
private fun checkFaceAuthCondition(): Boolean {
return LifeAccountAuthDataManager.personalAuthData.realName.isNotEmpty()
&& LifeAccountAuthDataManager.personalAuthData.idCardNum.isNotEmpty()
&& LifeAccountAuthDataManager.personalAuthData.idCardPortraitFaceObjectKey.isNotEmpty()
&& LifeAccountAuthDataManager.personalAuthData.idCardNationalEmblemFaceObjectKey.isNotEmpty()
}
/**
* 通过Uri获取文件全路径
* 适配Android Q
......
......@@ -84,8 +84,9 @@
android:layout_width="27dp"
android:layout_height="27dp"
android:layout_marginEnd="2dp"
android:background="@drawable/selector_protocol_check"
android:button="@null" />
android:button="@drawable/selector_protocol_check"
android:clickable="true"
android:focusable="true" />
<com.yidian.nightmode.widget.YdTextView
android:layout_width="wrap_content"
......
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