之前直接照着自己的理解罗列了下腾讯云的文档,然后被喷了,那么直接提供代码把。
调用方法
var userBean = UserBean()
userBean.name = ""//验证姓名
userBean.idNo = ""// 身份证号
userBean.userId = "123456"
FaceVerifySuper.setListener(mContext, userBean, object : FaceVerifySuper.OnTencentRequestListener {
override fun faceVerifySuccess() {
}
override fun faild() {
}
})
}
具体实现
APP_ID,SECRT, keyLicence,这3个参数要自己填写
import android.annotation.SuppressLint
import android.content.Context
import android.content.Context.WIFI_SERVICE
import android.net.wifi.WifiManager
import android.nfc.Tag
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import com.google.common.hash.Hashing
import com.hjq.toast.ToastUtils
import com.webank.facelight.contants.WbCloudFaceContant
import com.webank.facelight.contants.WbFaceError
import com.webank.facelight.listerners.WbCloudFaceVeirfyLoginListner
import com.webank.facelight.tools.WbCloudFaceVerifySdk
import okio.HashingSink
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.HashMap
import kotlin.math.log
@SuppressLint("StaticFieldLeak")
object FaceVerifySuper {
var TAG = "FaceVerify"
val APP_ID = ""
val SECRT = ""
val GRANT_TYPE = "client_credential"
val VERSION = "1.0.0"
val TENCENT_BASE_URL = "https://idasc.webank.com/api/"
var onTencentRequestListener: OnTencentRequestListener? = null
var userBean: UserBean? = null
var mContext: Context? = null
fun setListener(mContext: Context, userBean: UserBean, onTencentRequestListener: OnTencentRequestListener) {
this.mContext = mContext
this.userBean = userBean
Log.e("Tag", "userBean====${userBean}")
this.onTencentRequestListener = onTencentRequestListener
doFaceVerify()
}
fun transferFaceSdk(verifyBean: TencentFaceVerifyBean) {
verifyBean?.wifiIp = "IP=" + getIpAddress(mContext!!)
var faceVerifyResult: FaceVerifyResult = FaceVerifyResult()
//腾讯云线下对接分配的 Licence
var keyLicence = ""
var verifyMsgBean = VerifyMsgBean()
verifyMsgBean.userId = verifyBean.userId
verifyMsgBean.wifiIp = verifyBean?.wifiIp
// verifyMsgBean.roleName = verifyBean.userBean?.roleName
Log.e("tag", " verifyBean.orderNo=======${verifyBean.orderNo}")
//传入数据
var data = Bundle();
var inputData = WbCloudFaceVerifySdk.InputData(
verifyBean.faceId,
verifyBean.orderNo,
verifyBean.wifiIp,
verifyBean.gps,
APP_ID,
VERSION,
verifyBean.noceStr,
verifyBean.userId,
verifyBean.sign,
verifyBean.verifyMode,
keyLicence);
data.putSerializable(WbCloudFaceContant.INPUT_DATA, inputData);
//个性化参数设置,可以不设置,不设置则为默认选项。
//是否显示成功结果页,默认显示,此处设置为不显示
data.putBoolean(WbCloudFaceContant.SHOW_SUCCESS_PAGE, false);
//是否展示刷脸失败页面,默认展示,此处设置为不显示
data.putBoolean(WbCloudFaceContant.SHOW_FAIL_PAGE, false);
//sdk样式设置,默认为黑色
//此处设置为白色
data.putString(WbCloudFaceContant.COLOR_MODE, WbCloudFaceContant.WHITE);
//设置选择的比对类型 默认为权威库网纹图片比对
//权威数据源比对 WbCloudFaceContant.ID_CRAD
//自带比对源比对 WbCloudFaceContant.SRC_IMG
//仅活体检测 WbCloudFaceContant.NONE
//此处设置权威数据源对比
// data.putString(WbCloudFaceContant.COMPARE_TYPE, WbCloudFaceContant.ID_CRAD);
//是否需要录制上传视频 默认需要,此处设置为需要
data.putBoolean(WbCloudFaceContant.VIDEO_UPLOAD, false);
//是否对录制视频进行检查,默认不检查,此处设置为不检查
data.putBoolean(WbCloudFaceContant.VIDEO_CHECK, false);
//设置是否打开闭眼检测,默认不检测,此处设置为检测
data.putBoolean(WbCloudFaceContant.ENABLE_CLOSE_EYES, true);
Log.e("FVPresenter", "\n========>>>>" + inputData + "\n")
//初始化 SDK,得到是否登录 SDK 成功的结果
WbCloudFaceVerifySdk.getInstance().initSdk(mContext, data, object : WbCloudFaceVeirfyLoginListner {
override fun onLoginSuccess() {
WbCloudFaceVerifySdk.getInstance().startWbFaceVeirifySdk(mContext) { result ->
if (result != null) {
verifyMsgBean.isSuccess = result.isSuccess
verifyMsgBean.sign = result.sign
verifyMsgBean.liveRate = result.liveRate
verifyMsgBean.similarity = result.similarity
verifyMsgBean.orderNo = result.orderNo
if (result.isSuccess) {
faceVerifyResult?.isSuccess = true
Log.d(TAG, "刷脸成功! Sign=" + result.sign + "; liveRate=" + result.liveRate +
"; similarity=" + result.similarity + "userImageString=" + result.userImageString)
Toast.makeText(mContext, "身份识别成功", Toast.LENGTH_SHORT).show()
onTencentRequestListener?.faceVerifySuccess()
} else {
val error = result.error
verifyMsgBean.verror = VerifyMsgBean.VError()
verifyMsgBean.verror?.domain = error.domain
verifyMsgBean.verror?.code = error.code
verifyMsgBean.verror?.desc = error.desc
verifyMsgBean.verror?.reason = error.reason
verifyMsgBean.error = verifyMsgBean.verror.toString()
if (error != null) {
Log.d(TAG, "刷脸失败!domain=" + error.domain + " ;code= " + error.code
+ " ;desc=" + error.desc + ";reason=" + error.reason)
if (error.domain == WbFaceError.WBFaceErrorDomainCompareServer) {
Log.d(TAG, "对比失败,liveRate=" + result.liveRate +
"; similarity=" + result.similarity)
}
onTencentRequestListener?.faild()
Toast.makeText(mContext, "刷脸失败!" + error.desc,
Toast.LENGTH_LONG).show()
} else {
Log.e(TAG, "sdk返回error为空!")
}
}
// listener.success(verifyBean, result)
} else {
verifyMsgBean.sdkNull = true
Log.e(TAG, "sdk返回结果为空!")
}
sumbitVerifyMsg(verifyMsgBean!!)
}
}
override fun onLoginFailed(error: WbFaceError?) {
Log.i(TAG, "onLoginFailed!")
// 通知页面失败
// listener.faild(verifyBean, error!!)
onTencentRequestListener?.faild()
if (error != null) {
verifyMsgBean.verror = VerifyMsgBean.VError()
verifyMsgBean.verror?.domain = error.domain
verifyMsgBean.verror?.code = error.code
verifyMsgBean.verror?.desc = error.desc
verifyMsgBean.verror?.reason = error.reason
verifyMsgBean.error = verifyMsgBean.verror.toString()
Log.e(TAG, "登录失败!domain=" + error.domain + " ;code= " + error.code
+ " ;desc=" + error.desc + ";reason=" + error.reason)
if (error.domain == WbFaceError.WBFaceErrorDomainParams) {
ToastUtils.show("传入参数有误!" + error.reason)
} else {
ToastUtils.show("登录刷脸sdk失败!" + error.desc)
// Toast.makeText(mContext, "登录刷脸sdk失败!" + error.desc, Toast.LENGTH_SHORT).show()
}
} else {
verifyMsgBean.sdkNull = true
Log.e(TAG, "sdk返回error为空!")
}
sumbitVerifyMsg(verifyMsgBean)
}
})
}
/**
* 人脸识别请求
*/
fun doFaceVerify() {
// 判断传入数据是否合法
if (onTencentRequestListener == null || userBean == null || Constants.isEmptyS(userBean!!.name, userBean!!.idNo, userBean!!.userId)) {
Log.e(TAG, "onTencentRequestListener${onTencentRequestListener}")
Log.e(TAG, "userBean!!.name${userBean!!.name}")
Log.e(TAG, "userBean!!.name${userBean!!.idNo}")
Log.e(TAG, "userBean!!.name${userBean!!.userId}")
ToastUtils.show("非法数据")
} else {
getAccessToken()
}
}
fun getFaceId(sgin: String, noceStr: String) {
var verifyBean = TencentFaceVerifyBean()
verifyBean.webankAppId = APP_ID
verifyBean.orderNo = Constants.getRandomNumber()
verifyBean.name = userBean?.name
verifyBean.idNo = userBean?.idNo
verifyBean.userId = userBean?.userId
verifyBean.sign = sgin
verifyBean.noceStr = noceStr
getRetroClientByTencentUrl().requestFaceId(Constants.Obj2RequestBody(verifyBean)).enqueue(object : Callback<TencentResponseBean> {
override fun onResponse(call: Call<TencentResponseBean>, response: Response<TencentResponseBean>) {
// 成功获取信息
if (OnRequestUtils.isTXResponseSuccess(response) && response.body()?.result?.faceId != null) {
verifyBean.faceId = response.body()?.result?.faceId
transferFaceSdk(verifyBean)
} else {
if (response.body()?.msg != null)
// doFaildOperational(response,-1)
ToastUtils.show("错误信息:" + response.body()?.msg)
onTencentRequestListener?.faild()
}
}
override fun onFailure(call: Call<TencentResponseBean>, t: Throwable) {
onTencentRequestListener?.faild()
}
})
}
// https://idasc.webank.com/api/oauth2/api_ticket
/**
* 获取NoceTicket
*/
fun getNonceTicket(t: TencentResponseBean) {
val requestMap = HashMap<String, String>()
requestMap.put("app_id", APP_ID);
requestMap.put("access_token", t.access_token!!);
requestMap.put("type", "NONCE");
requestMap.put("version", VERSION);
requestMap.put("user_id", userBean!!.userId!!);
getRetroClientByTencentUrl().requestNonceTicket(requestMap).enqueue(object : Callback<TencentResponseBean> {
override fun onResponse(call: Call<TencentResponseBean>, response: Response<TencentResponseBean>) {
if (OnRequestUtils.isTXResponseSuccess(response)
&& response.body()?.tickets?.size!! > 0
&& response.body()?.tickets?.get(0)!!.value != null
) {
var noceStr: String = Constants.getRandomNumber()
var values = ArrayList<String>()
values.add(APP_ID)
values.add(userBean!!.userId!!) //合作方自行分配(与 SDK 里定义的 userId 保持一致)
values.add(VERSION)
values.add(noceStr)// 合作方自行生成(与 SDK 里定义的随机数保持一致)
var sign = signGenerate(values, response.body()!!.tickets!!.get(0)!!.value!!) // 获取签名
// 执行获取 faceId 方法
getFaceId(sign, noceStr)
} else {
doFaildOperational(response, 1)
onTencentRequestListener?.faild()
}
}
override fun onFailure(call: Call<TencentResponseBean>, t: Throwable) {
onTencentRequestListener?.faild()
}
})
}
/**
* 获取Access Token
*/
@Throws()
fun getAccessToken() {
val requestMap = HashMap<String, String>()
requestMap.put("app_id", APP_ID);
requestMap.put("secret", SECRT);
requestMap.put("grant_type", GRANT_TYPE);
requestMap.put("version", VERSION);
getRetroClientByTencentUrl().requestAccessToken(requestMap).enqueue(object : Callback<TencentResponseBean> {
override fun onResponse(call: Call<TencentResponseBean>, response: Response<TencentResponseBean>) {
// 判断返回是否成功
if (OnRequestUtils.isTXResponseSuccess(response) && response.body()?.access_token != null) {
getNonceTicket(response.body()!!)
} else {
doFaildOperational(response, 0)
onTencentRequestListener?.faild()
}
}
override fun onFailure(call: Call<TencentResponseBean>, t: Throwable) {
onTencentRequestListener?.faild()
}
})
}
/**
* 签名算法
* @param values
* @param ticket
* @return
*/
fun signGenerate(values: ArrayList<String>, ticket: String): String {
// values.removeAll(Collections.singleton(null))// remove null
values.add(ticket)
Collections.sort(values)
val sb = StringBuilder()
for (s in values) {
sb.append(s)
}
return Hashing.sha1().hashString(sb, Charsets.UTF_8).toString().toUpperCase()
}
/**
* 腾讯云请求配置
*/
fun getRetroClientByTencentUrl(): RequsetDataInterface {
return RetroClient.getApiService(TENCENT_BASE_URL)
}
/**
* 腾讯云正常响应,返回不通过处理
*/
fun doFaildOperational(response: Response<TencentResponseBean>, type: Int) {
var failMsg: StringBuffer = StringBuffer("Faild code :")
.append(response.body()?.code)
.append(" msg :")
.append(response.body()?.msg)
if (type == 0 && response.body()?.access_token == null) {
failMsg.append("Bad Response ACCESS_TOKEN = NULL")
} else if (type == 1 && response.body()?.tickets == null) {
failMsg.append("Bad Response NONCE_TICKET = NULL")
}
ToastUtils.show(failMsg)
}
/**
* 提交此次验证信息结果至己方平台
*/
fun sumbitVerifyMsg(v: VerifyMsgBean) {
}
/**
* 获取当前设备wifi IP
*/
private fun getIpAddress(mContext: Context): String {
val wm = mContext.getApplicationContext().getSystemService(WIFI_SERVICE) as WifiManager
val ipAddressInt = wm.connectionInfo.ipAddress
val ipAddress = String.format(Locale.getDefault(), "%d.%d.%d.%d", ipAddressInt and 0xff, ipAddressInt shr 8 and 0xff, ipAddressInt shr 16 and 0xff, ipAddressInt shr 24 and 0xff)
return ipAddress
}
/**
* 回调响应
*/
interface OnTencentRequestListener {
fun faceVerifySuccess()
fun faild()
}
}