签盾开放平台-电子签约服务
    签盾开放平台-电子签约服务
    • 接入流程介绍
    • 应用创建流程
    • 前端接入文档
    • 开发前必读
      • 常用接口清单和关键流程
      • 公共请求格式
    • 帮助文档
      • 印章指定位置
      • 静默签使用说明
    • 实名认证
      • 个人认证
        • 个人认证项
          • 个人身份二要素核验
          • 个人运营商三要素核验
          • 个人人脸核验(H5适配)
          • 个人人脸核验查询
          • 发送短信验证码
          • 校验短信验证码
          • 个人银行卡四要素核验
        • 个人实名认证地址(页面)
      • 企业认证
        • 企业认证项
          • 企业四要素核验
          • 企业三要素核验
          • 发起打款认证(正向打款)
          • 验证打款金额(正向打款)
          • 查询打款进度(正向打款)
          • 企业经办人授权书认证-上传
          • 企业经办人授权书认证-查询
          • 查询打款银行信息
        • 企业实名认证地址(页面)
      • 查询认证信息
        GET
    • 用户管理
      • 个人用户
        • 修改个人用户
        • 创建已认证个人用户
        • 查询个人用户信息
      • 企业用户
        • 查询企业用户信息
        • 创建已认证企业用户
      • 创建未认证用户(暂不支持企业)
        POST
    • 文件相关
      • 上传文件
        POST
      • 基于模板生成文件
        POST
    • 合同相关
      • 通过文件发起合同
        POST
      • 查询签署方信息
        GET
      • 下载合同文件及附件
        GET
      • 合同查询
        GET
      • 获取合同签署链接(页面)
        POST
      • 无感签署(申请开放)
        POST
      • 获取拖章定位页面
        POST
    • 印章管理
      • 查询印章列表
        GET
      • 查询印章详情
        GET
      • 印章静默签授权地址(H5页面)
        POST
    • 接口回调
      • 回调接入文档
      • 获取回调信息
      • 回调成功确认
    • 开放接口
      • 短信验证码
      • 通知短信发送
      • 身份证OCR
      • 营业执照OCR
      • 银行卡OCR

    前端接入文档

    移动端接入文档#

    注意:
    📌
    注意:由于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" ></web-view>
        </view>

    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  //填写得重定向链接  有需要回调获取得参数可以拼接在这里
                  }
              }

    4.uniapp的安卓端可使用原生插件进行接入#

    插件

    小程序接入#

    1.在小程序中创建一个包含webview的页面,并绑定message事件#

        <view >
          <web-view src="{{url}}" bindmessage="message"></web-view>
        </view>

    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.登录小程序公众平台,在开发管理中,添加业务域名
    图片1(1).png
    2.先下载校验文件,然后将文件发给我方,待我方将文件添加至域名根目录之后,再将我方域名 https://xxxxxx.com 添加至业务域名中,(域名校验完成后,校验文件即可删除)
    图片1(2).png

    iOS APP 接入#

    1.iPhone 的兼容性适配,需在配置里加上摄像头和麦克风的使用权限。App 的 info.plist 中加入:#

    .NSMicrophoneUsageDescription
    .NSCameraUsageDescription

    2.使用 WKWebView 时,需要通过 WKWebViewConfiguration 配置允许使用相机:#

        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
        config.allowsInlineMediaPlayback = YES;
    6ab481c7ad6d1da3b7c30d636d1911a.png
    文件

    3.重写WebViewClient,获取返回结果, 监听url,当url格式为success://app?code=xx&msg=授权成功&redirectUrl=xxx时,认证成功,进行相应操作#

    Android APP接入#

    1.app中创建一个包含webview的页面#

    2.引入工具类,将 WBH5FaceVerifySDK.java 文件拷贝到项目中#

    文件

    3.申请权限#

    在 Manifest.xml 文件中增加申请以下权限
        <uses-permission android:name="android.permission.CAMERA" />
        <uses-permission android:name="android.permission.INTERNET" />

    4.设置 WebSettings#

    调用 WebView.loadUrl(String url) 前一行添加如下代码设置 WebSettings#
        /**
        * 对 WebSettings 进行设置:添加 ua 字段和适配 h5 页面布局等
        * @param mWebView  第三方的 WebView 对象
        * @param context  第三方上下文
        */
        WBH5FaceVerifySDK.getInstance().setWebViewSettings(mWebView,getApplicationContext());
    2ff8954e555f0ecb7773c05ea304115.png

    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){ 
                    this.request=request;
                    request.grant(request.getResources());
                    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){                   
                            //授权
                            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<Uri> uploadMsg) {
            //因为H5页面中有调用系统相机、相册功能,所以此处需要配置
            this.uploadMessage = uploadMsg;
            this.openImageChooserActivity();
        }
        /**
         * android端接收H5端发来的请求
         For Android >= 3.0
         */
        public void openFileChooser(ValueCallback<Uri> 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<Uri> 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<Uri> 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;
            }
    
    上一页
    应用创建流程
    下一页
    常用接口清单和关键流程
    Built with