uniapp开发app端 扫脸认证 || 人脸认证 || 活体认证

2,993 阅读4分钟

一、前言

遇到个最近需求,要求使用uniapp写app端,并且实现一个类似人脸认证的功能。因为第三方活体认证的对接费用有点贵,这时候就到了折磨时刻了。因为之前写过小程序类似的功能,想着<camera>标签梭哈一下,完事。结果大家都知道,当你以为👌的时候,那就很不ok了。在uniapp中写app,是使用不了<camera>标签的。

这该怎么办呢?于是查询资料,开始了骚操作之旅·····

二、需求

1、这个需求呢主要是为了实现用户到达某一个地点区域内,进行打卡,进行验证是否为本人打卡和是否在打卡区域内。
2、由于uniapp在开发app中,不能够使用像小程序直接使用camera标签来直接获取摄像头的影像将其展示在页面上供使用者查看。所以这里采用了另一种方式来解决这个问题。
3、这里这个需求所采用的方式是:前端进行摄像头的获取,并把实时影像放在页面中展示给使用者,利用切片的方式,将切片图传的给后端。后端采用阿里的人脸识别API进行切片的对比。 返回给前端此时是否为本人打卡,并返回打卡是否成功的信息

三、需要解决的核心问题

1、前端如何将用户的前摄像头内容进行展示在页面中给使用者查看?(本篇也是主要为要这个点进行讲解)。
2、活体的识别交给前端做还是后端做?(这个点上边有说,主要是后端进行阿里的API进行人脸识别和活体的识别)
3、当你觉得一切完美的时候,常常事情就不完美了。还有一个比较要注意的点,当我们写这个认证组件的时候,通常我们使用的是 .vue 的文件,但是在这里我们的这个组件我们要建成 .nvue 的,原因下面会解释的。

四、前端如何进行摄像头内容的获取并展示给用户

由于需求是使用uniapp进行开发app端,无法使用设备的摄像头。不能够像uniapp写小程序一样可以直接使用camera标签进行将摄像头的内容进行获取展示。
思路:
1、既然无法像小程序一样直接使用camera标签,那我们可以采用直播推流的方式,进行获取摄像头的内容,然后在上面覆盖一层遮罩进行将不需要的部分进行遮挡,可见区域内就会形成一个我们想要的摄像头区域。
2、直播推流 组件 <live-pusher>,由使用的是<live-pusher>组件,普通的view盒子是无法再其上面进行遮挡的,所以需要使用到<cover-image>组件进行作为遮罩层来使用。
3、至于我们这个认证组件为什么要写成.nvue的文件,原因呢也很简单。其实在<live-pusher>的使用文档上也有说明,.vue中使用<live-pusher>组件需要vue版本3.4.1+上的版本,在其以下的版本想使用只能把文件建成.nvue。
4、说明:
组件的使用说明在这里就不多说了,详细可以直接点击下面的官方文档链接进行查看。
<live-pusher>组件说明文档
<cover-image>组件说明文档
5、具体代码来啦!!!

    <!-- HTML大致结构,可根据自己需求进行配置 -->
    <!-- 例:style配置,按照自己的项目情况自行配置即可 -->
    <live-pusher
        id='livePusher'
        ref="livePusher"
        class="livePusher"
        url=""
        mode="SD"
        :muted="true"
        :enable-camera="true"
        :auto-focus="true"
        :beauty="1"
        whiteness="2"
        aspect="9:16"
        local-mirror="disable"
        @error = "error"
        :style="[{
            height: '700rpx',
            'margin-top': '200rpx' ,
            width:'750rpx',
        }]"
    ></live-pusher>

    <cover-image
        class="cover-image"
        style="
            width: 750rpx;
            height: 698rpx;
            transform: scale(1.2);
        "
        src="@/static/xxxx/camera_bg.png"
    />

js逻辑部分

data() {
    return {
        livePusher: '', // livePusher实例
        snapshotInfo: '', // 快照信息
        showCountDown: false, // 拍摄倒计时
        timeOut: 3, // 签到倒计时
        timeFlag: null, // 定时器
        isPass: null, // 是否通过人脸认证
        passMsg: '', // 提示信息
    }
},
onReady() { // 初始化
    // 创建 live-pusher 上下文 livePusherContext 对象
    this.livePusher = uni.createLivePusherContext("livePusher", this);
},
mounted() {
    const that_ = this
    setTimeout(function() { // 进入页面1秒后开启预览
        that_.startPreview()
    }, 1000)

},
destroyed() { // 注销页面时清楚定时器
    clearInterval(this.timeFlag)
    uni.hideLoading();
},
methods: {
    // 开始预览
    startPreview() {
        const _that = this
        this.livePusher.startPreview({
        success: (res)=> {
            this.showCountDown = true
            _that.handleSetTime()
            }
        })
    },
    // 开始预览后开始倒计时并拉取接口并进行对比
    handleSetTime () {
        this.timeFlag = setInterval(async () => {
            // 倒计时
            if (this.timeOut > 0) {
                this.timeOut--
            }
            
            // 取得快照
            if (this.timeOut == 1) {
                this.livePusher.snapshot({
                    success: (res) => {
                        this.snapshotInfo = res.message
                    }
                })
            }
            
            // 进行快照人脸认证
            if (this.timeOut <= 0) {
                uni.showLoading({
                    title: '验证中...'
                })
                
                try{
                    // 拉取后端接口(后端通过阿里API封装的接口)
                    // 参数1:接口地址 参数2:请求人的id 参数3:快照信息
                    const res = await file_request("/xxx/xxxx", { xx: this.xxx }, this.snapshotInfo.tempImagePath)
                    const { status, msg } = JSON.parse(res)

                    status == 200this.isPass = 1 ? this.isPass = 2

                    this.passMsg = msg

                } catch (e) {
                    this.$refs.uToast.show({
                        type: 'error',
                        message: err,
                        duration: 1500,
                    });
                    uni.redirectTo({ // 认证接口出错时返回的页面
                        url: `/pages/xxx/xxxxx`
                    })
                }
                uni.hideLoading()
                
                // 验证成功后返回上一层,并把是否通过、提示信息、快照信息给上层页面,
                uni.redirectTo({
                    url: `/pages/xxx/xxxxx?isPass=${this.isPass}&passMsg=${this.passMsg}&snapshotInfoHerder=${this.isPass == 1 ? this.snapshotInfo.tempImagePath : ''}`
                })
            }
        }, 1000)
    }
}

致敬

如果按照步骤成功完成自己手撸的人脸认证,就给本文章点个赞吧!😁😁😁