移动端(Android,IOS,微信小程序,H5)--接入
移动端接入文档
注意:
📌
注意:由于APP端系统多样,建议使用H5端的方式接入,操作完成后跳转至自身的H5端中转页面,可以根据自身需要进行数据查询以及App跳转等操作
📌
获取授权链接时一定要根据实际情况,来配置clientType(客服端)参数,
app: 原生android与ios端APP
h5: h5页面(uniapp端app建议以此方式接入)
wechat_applet: 小程序
uniapp:uniapp混合开发(暂无,可通过跳转至中转页实现)
H5 接入
1.直接打开获取的授权链接
2.授权完成会重定向至设置的redirectUrl url格式为 redirectUrl+'success=true&code=xxx&msg=授权成功
📌
注意:合作方如果使用 iframe 框架,需要给 iframe 开启相机权限 allow="camera;",方可正常使用实时检测人脸核身功能。
示例:<iframe allow="camera;"></iframe>
uniapp接入(暂无,可跳转至自己项目的中转H5页面来实现)
1.在应用中创建一个包含webview的页面,并绑定message事件
<view >
<web-view :src="src" @message="message" >
2.获取授权链接,并赋值给url
3.进入授权页面,授权成功后,在message中接收返回参数,并进行相应操作
message(e){
//接收参数为一个data对象
console.log('接收到参数--'+JSON.stringify(e.detail.data))
data内容为
data:{
success:true,
code:this.code,//授权链接中得code
msg:'授权成功',
redirectUrl:this.redirectUrl //填写得重定向链接 有需要回调获取得参数可以拼接在这里
}
}
小程序接入
1.在小程序中创建一个包含webview的页面,并绑定message事件
<view >
<web-view src="{{url}}" bindmessage="message">
2.获取授权链接,并赋值给url
3.进入授权页面,授权成功后,在message中接收返回参数,并进行相应操作
message(e){
//接收参数为一个data对象
console.log('接收到参数--'+JSON.stringify(e.detail.data))
data内容为
data:{
success:true,
code:this.code,//授权链接中得code
msg:'授权成功',
redirectUrl:this.redirectUrl //填写得重定向链接 有需要回调获取得参数可以拼接在这里
}
}
注:
(1).由于小程序消息需要通过后退,跳转,销毁,分享等触发,我们是通过后退触发,所以小程序会默认返回上一页
(2).由于小程序打开第三方h5页面需要配置业务域名,所以需要用户将我方域名添加至小程序业务域名中,详细步骤如下:
1.登录小程序公众平台,在开发管理中,添加业务域名
2.先下载校验文件,然后将文件发给我方,待我方将文件添加至域名根目录之后,再将我方域名 https://saas-h5.qiandun365.com 添加至业务域名中,(域名校验完成后,校验文件即可删除)
iOS APP 接入
1.iPhone 的兼容性适配,需在配置里加上摄像头和麦克风的使用权限。App 的 info.plist 中加入:
.NSMicrophoneUsageDescription
.NSCameraUsageDescription
2.使用 WKWebView 时,需要通过 WKWebViewConfiguration 配置允许使用相机:
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.allowsInlineMediaPlayback = YES;
3.重写WebViewClient,获取返回结果, 监听url,当url格式为success://app?code=xx&msg=授权成功&redirectUrl=xxx时,认证成功,进行相应操作
Android APP接入
1.app中创建一个包含webview的页面
2.引入工具类,将 WBH5FaceVerifySDK.java 文件拷贝到项目中
3.申请权限
在 Manifest.xml 文件中增加申请以下权限
4.设置 WebSettings
调用 WebView.loadUrl(String url) 前一行添加如下代码设置 WebSettings
/**
- 对 WebSettings 进行设置:添加 ua 字段和适配 h5 页面布局等
- @param mWebView 第三方的 WebView 对象
- @param context 第三方上下文
*/
WBH5FaceVerifySDK.getInstance().setWebViewSettings(mWebView,getApplicationContext());
5.重写 WebChromeClient
调用 WebView.loadUrl(String url) 前,WebView 必须调用 setWebChromeClient(WebChromeClient webChromeClient),并重写 WebChromeClient 的如下函数:
/**
*TRTC 刷脸模式配置,这里负责处理来自H5页面发出的相机权限申请
- @param request 来自H5页面的权限请求
*/
@Override
public void onPermissionRequest(PermissionRequest request) {
if (request!=null&&request.getOrigin()!=null&&WBH5FaceVerifySDK.getInstance().isTencentH5FaceVerify(request.getOrigin().toString())){ //判断是腾讯h5刷脸的域名
Log.d(TAG,"onPermissionRequest 收到腾讯h5刷脸页面的相机授权");
this.request=request;
if (activity!=null){
//申请相机权限,申请权限的代码demo仅供参考,合作方可根据自身业务定制
activity.requestCameraPermission();
}
}
}
/**
- 相机权限申请成功后,拉起TRTC刷脸模式进行实时刷脸验证
/
public void enterTrtcFaceVerify(){
if (Build.VERSION.SDK_INT>Build.VERSION_CODES.LOLLIPOP){ // android sdk 21以上
if (request!=null&&request.getOrigin()!=null){
if (WBH5FaceVerifySDK.getInstance().isTencentH5FaceVerify(request.getOrigin().toString())){ //判断是腾讯h5刷脸的域名,如果合作方对授权域名无限制的话,这个if条件判断可以去掉,直接进行授权即可。
//授权
request.grant(request.getResources());
request.getOrigin();
}
}else {
if (request==null){
Log.d(TAG,"enterTrtcFaceVerify request==null");
if (webView!=null&&webView.canGoBack()){
webView.goBack();
}
}
}
}
// For Android < 3.0
public void openFileChooser(ValueCallback uploadMsg) {
//因为H5页面中有调用系统相机、相册功能,所以此处需要配置
this.uploadMessage = uploadMsg;
this.openImageChooserActivity();
}
/* - android端接收H5端发来的请求
For Android >= 3.0
*/
public void openFileChooser(ValueCallback uploadMsg, String acceptType) {
Log.d(TAG,"openFileChooser---Android >= 3.0----");
if(WBH5FaceVerifySDK.getInstance().recordVideoForApiBelow21(uploadMsg, acceptType,activity))
return;
//因为H5页面中有调用系统相机、相册功能,所以此处需要配置
this.uploadMsg = uploadMsg;
this. openImageChooserActivity();
}
// For Android >= 4.1 录制模式中,点击h5页面的录制按钮后触发的系统方法
public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) {
if (WBH5FaceVerifySDK.getInstance().isTencentH5FaceVerify(null,null,acceptType)){ //判断是腾讯h5刷脸的域名
this.uploadMsg=uploadMsg;
this.acceptType=acceptType;
if (activity!=null){
//申请系统的相机、录制、sd卡等权限
activity.requestCameraAndSomePermissions(true,false);
}
}else{
//因为H5页面中有调用系统相机、相册功能,所以此处需要配置
this.uploadMessage = uploadMsg;
this..openImageChooserActivity();
}
}
// For Lollipop 5.0+ Devices 录制模式中,点击h5页面的录制按钮后触发的系统方法
@TargetApi(21)
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
if (WBH5FaceVerifySDK.getInstance().isTencentH5FaceVerify(webView,fileChooserParams,null)){ //判断是腾讯h5刷脸的域名
this.webView=webView;
this.filePathCallback=filePathCallback;
this.fileChooserParams=fileChooserParams;
if (activity!=null){
//申请系统的相机、录制、sd卡等权限
activity.requestCameraAndSomePermissions(false,false);
}
}else{
//因为H5页面中有调用系统相机、相册功能,所以此处需要配置
this.uploadMessage = uploadMsg;
this..openImageChooserActivity();
}
return true;
}
//录制模式中,拉起系统相机进行录制视频
public boolean enterOldModeFaceVerify(boolean belowApi21){
if (belowApi21){ // For Android < 5.0
if (WBH5FaceVerifySDK.getInstance().recordVideoForApiBelow21(uploadMsg, acceptType, activity)) {
return true;
}
}else { // For Android >= 5.0
if (WBH5FaceVerifySDK.getInstance().recordVideoForApi21(webView, filePathCallback, activity,fileChooserParams)) {
return true;
}
}
return false;
}
如果第三方已重写以上函数,只要将如上述所示的函数体内容添加至第三方的对应函数体首行即可。
如果第三方没有重写以上函数,则直接按上述所示重写。
WebView 不要使用 layerType 属性,否则导致刷脸界面白屏。
6.重写 Activity
WebView 所属的 Activity 必须重写如下函数:
public ValueCallback uploadMessage;
public ValueCallback<Uri[]> uploadMessageAboveL;
private static final String TAG = "H5Activity";
private final static int FILE_CHOOSER_RESULT_CODE = 10000;
private static final int PERMISSION_QUEST_TRTC_CAMERA_VERIFY = 12;
private static final int PERMISSION_QUEST_CAMERA_RECORD_VERIFY = 11;
Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult --------"+requestCode);
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == VIDEO_REQUEST) {//录制模式中,调用系统相机录制完视频后再回到当前app页面
if (WBH5FaceVerifySDK.getInstance().receiveH5FaceVerifyResult(requestCode, resultCode, data)) {
return;
}
}else if (requestCode==PERMISSION_QUEST_TRTC_CAMERA_VERIFY){ //trtc模式中,申请相机权限时,从系统设置页面跳转回当前app页面的处理。由于权限申请逻辑demo仅供参考,合作方自己处理即可。
requestCameraPermission();
}else if (requestCode==PERMISSION_QUEST_CAMERA_RECORD_VERIFY){//录制模式中,申请权限时,从系统设置页面跳转回当前app页面的处理。由于权限申请逻辑demo仅供参考,合作方自己处理即可。
requestCameraAndSomePermissions(false);
}else if (requestCode == FILE_CHOOSER_RESULT_CODE) {
if (null == uploadMessage && null == uploadMessageAboveL) return;
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
if (uploadMessageAboveL != null) {
onActivityResultAboveL(requestCode, resultCode, data);
} else if (uploadMessage != null) {
uploadMessage.onReceiveValue(result);
uploadMessage = null;
}
}else{
//此处为选择文件的系统相机相册回调
if (Build.VERSION.SDK_INT >= 21) {
chooseAbove(resultCode, data);
} else {
chooseBelow(resultCode, data);
}
}
//唤起系统相机与相册的方法
public void openImageChooserActivity() {
String filePath = Environment.getExternalStorageDirectory() + File.separator;
String fileName = "IMG_" + DateFormat.format("yyyyMMdd_hhmmss", Calendar.getInstance(Locale.CHINA)) + ".jpg";
imageUri = Uri.fromFile(new File(filePath + fileName));
//相册相机选择窗
Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
Intent Photo = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
Intent chooserIntent = Intent.createChooser(Photo, "选择上传方式");
chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Parcelable[]{captureIntent});
startActivityForResult(chooserIntent, 1);
}
/**
- Android API < 21(Android 5.0) 版本的回调处理
*/
public void chooseBelow(int resultCode, Intent data) {
Log.e("Base", "调用方法 chooseBelow");
if (Activity.RESULT_OK == resultCode) {
updatePhotos();
if (data != null) {
// 这里是针对文件路径处理
Uri uri = data.getData();
if (uri != null) {
Log.e("Base", "系统里取到的图片:" + uri.toString());
uploadMessage.onReceiveValue(uri);
} else {
uploadMessage.onReceiveValue(null);
}
} else {
// 以指定图像存储路径的方式调起相机,成功后返回data为空
Log.e("Base", "自己命名的图片:" + imageUri.toString());
uploadMessage.onReceiveValue(imageUri);
}
} else {
uploadMessage.onReceiveValue(null);
}
uploadMessage = null;
}
/**
-
Android API >= 21(Android 5.0) 版本的回调处理
*/
public void chooseAbove(int resultCode, Intent data) {
Log.e("Base", "调用方法 chooseAbove " +data);if (Activity.RESULT_OK == resultCode) {
updatePhotos();if (data != null) {
// 这里是针对从文件中选图片的处理
Uri[] results;
Uri uriData = data.getData();
if (uriData != null) {
results = new Uri[]{uriData};
for (Uri uri : results) {
Log.e("Base", "系统里取到的图片:" + uri.toString());
}
uploadMessageAboveL.onReceiveValue(results);
} else {
uploadMessageAboveL.onReceiveValue(null);
}
} else {
Log.e("Base", "自己命名的图片:" + imageUri.toString());
uploadMessageAboveL.onReceiveValue(new Uri[]{imageUri});
}
} else {
uploadMessageAboveL.onReceiveValue(null);
}
uploadMessageAboveL = null;
}
//发送广播进行更新相册
private void updatePhotos() {
// 该广播即使多发(即选取照片成功时也发送)也没有关系,只是唤醒系统刷新媒体文件
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(imageUri);
sendBroadcast(intent);
}
7.重写WebViewClient,获取返回结果
重写WebViewClient, 监听url,当url格式为success://app?code=xx&msg=授权成功&redirectUrl=xxx时,认证成功,进行相应操作
mWebView.setWebViewClient(new MyWebViewClient());
private class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url == null) {
return false;
}
Uri uri = Uri.parse(url);
// 与JS端定义好协议: 一般协议格式是Scheme(协议头)+ Authority(协议名)
// uri.getScheme() //返回的请求协议头 success
// uri.getAuthority() //协议名 app
//uri.getQueryParameter 获取链接参数 uri.getBooleanQueryParameter 参数有(code,msg,redirectUrl)
if (uri.getScheme().equals("http") || uri.getScheme().equals("https")) {
view.loadUrl(url);
return true;
} else if (uri.getScheme().equals("success")){
//此时表示授权成功。执行授权成功的逻辑
// Toast.makeText(H5Activity.this, "授权成功", Toast.LENGTH_LONG).show();
// try {
// Thread.sleep(2000);
// } catch (InterruptedException e) {
// throw new RuntimeException(e);
// }
finish();
return true;
}
return true;
}