mpvue小程序实现人脸识别/视频录制/身份验证/CryptoJS加密 等功能
先看效果图
mpvue小程序与数据宝对接实现人脸识别/视频录制/身份验证/CryptoJS 加密 等功能关键代码 index.vue
<template>
<div class="page-body">
<!-- 人脸识别引导提示内容 图一 -->
<cover-view v-if="showFaceTip" class="showFaceClass">
<cover-image :src="imgUrl.faceTip" style="width:100%;height:1100rpx;" />
<button class="startButton" @click="runRecord" style="width:500rpx;">开始录制</button>
</cover-view>
<!-- 录制视频代码 图二 -->
<div v-else class="showCameraBox">
<cover-view class="longTip" v-show="longTip">'长按'底部按钮录制一段3~5S视频</cover-view>
<div class="cameraBox">
<camera
@error="error"
v-show="!imgsrc"
device-position="front"
flash="on"
style="width: 100%;height:100%;"
></camera>
<img v-show="imgsrc" mode="widthFix" :src="imgsrc" style="width:100%;height:100%;" />
</div>
<div class="btnRecord">
<canvas canvas-id="firstCanvas" class="canvas"></canvas>
<button
v-if="cameraBtn"
style="cursor:pointer;"
class="wrap"
id="wrap"
:style="style"
@touchstart="takePhoto"
@touchend="handleTouchEnd"
@longpress="handleLongPress"
>
<div class="inner" :style="style2"></div>
</button>
<button v-else style="cursor:pointer;" class="wrap" id="wrap" @tap="takePhoto">
<div class="inner" :style="style2"></div>
</button>
</div>
</div>
<!-- 弹框提示 -->
<mp-loading :showLoading="isShowLoading" loadingText="加载中..." :mask="isShowMask"></mp-loading>
</div>
</template>
<style scoped>
.longTip {
position: fixed;
z-index: 99999999;
top: 60rpx;
color: rgba(212, 141, 52, 1);
}
.showFaceClass {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
background: #000000;
display: flex;
align-items: center;
flex-direction: column;
z-index: 99999999;
}
.showCameraBox {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
background: #000000;
z-index: -1;
display: flex;
align-items: center;
flex-direction: column;
}
.startButton {
position: fixed;
bottom: 200rpx;
width: 490rpx;
height: 91rpx;
padding: 0 60rpx;
box-sizing: border-box;
text-align: center;
line-height: 91rpx;
background: rgba(212, 141, 52, 1);
box-shadow: 0px 18px 12px 0px rgba(212, 141, 52, 0.12);
border-radius: 16rpx;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
}
/* 视频录制 */
.cameraBox {
width: 100%;
height: 80vh;
}
/*长按录制视频按钮*/
.btnRecord {
display: flex;
justify-content: center;
align-items: center;
height: 20vh;
width: 100%;
background: #000000;
}
/* 外圆 */
.wrap {
cursor: pointer;
box-sizing: border-box;
width: 100px;
height: 100px;
background: rgba(255, 255, 255, 0.7);
border-radius: 50%;
/* margin: 100rpx auto; */
overflow: hidden;
transition: all 0.5s;
transform-origin: center;
z-index: 999;
}
/* canvas */
.canvas {
position: absolute;
width: 100%;
height: 20vh;
z-index: 999;
}
/* 内圆 */
.inner {
box-sizing: border-box;
width: 70px;
height: 70px;
background: #fff;
margin: 15px auto;
border-radius: 50%;
transition: all 0.5s;
transform-origin: center;
/* overflow: hidden; */
}
button::after {
/*button的边框样式是通过::after方式实现的*/
border: none;
}
</style>
<script>
//加密
const CryptoJS = require("crypto-js");
function encrypt(str, key, iv) {
key = CryptoJS.enc.Utf8.parse(key);
iv = CryptoJS.enc.Utf8.parse(iv);
const encryptedStr = CryptoJS.AES.encrypt(str, key, {
iv: iv,
mode: CryptoJS.mode.CFB,
padding: CryptoJS.pad.NoPadding
});
var result = encryptedStr.toString();
return result;
}
export default {
data() {
return {
imgUrl: {
faceTip: this.$myObj.api + "faceTip.png"
},
isShowLoading: false,
showFaceTip: true,
style: "",
style2: "",
style3: "",
startDeg: 0,
endDeg: 0,
num: 0.02,
timer: null,
timer2: null,
src: "",
videoSrc: "", //录像的视频
imgsrc: "", //视频中的图片
ctx: {},
context: "",
appkey: "",
imageId: "", //图片字符串标识符
objStr: "",
longTip: false,
cameraBtn: true //控制录像或者拍照按钮
};
},
onLoad(options) {
this.cameraBtn = true;
this.ctx = {};
this.timer = null;
this.timer2 = null;
this.longTip = false; //长按提示
this.src = "";
this.videoSrc = "";
this.imgsrc = "";
this.isShowLoading = false;
this.style = "";
this.style2 = "";
this.style3 = "";
this.startDeg = 0;
this.endDeg = 0;
this.imageId = "";
let objStr = options.objStr;
this.objStr = objStr;
//创建节点选择器
var query = wx.createSelectorQuery();
//选择id
query.select("#wrap").boundingClientRect();
var that = this;
query.exec(function(res) {
//res就是 所有标签为wrap的元素的信息 的数组 //取高度
// console.log(res[0].height);
that.r = res[0].height / 2;
// console.log("半径", that.r);
});
//默认显示人脸认证引导页
this.showFaceTip = true;
//数据宝产品初始化 获取appKey
this.initProduct();
},
onShow() {
clearInterval(this.timer);
clearInterval(this.timer2);
this.getSetting(); //获取设置信息
},
onReady(res) {
if (wx.createCameraContext()) {
this.ctx = wx.createCameraContext();
} else {
// 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
wx.showModal({
title: "提示",
content:
"当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。"
});
}
},
onUnload() {
this.ctx = {};
clearInterval(this.timer);
clearInterval(this.timer2);
wx.hideLoading();
},
methods: {
error(e) {
console.log("error", e);
},
//获取设置信息
getSetting() {
wx.getSetting({
success(res) {
// console.log("authSetting", res);
var recordSetting = res.authSetting["scope.record"];
var cameraSetting = res.authSetting["scope.camera"];
if (!recordSetting) {
wx.authorize({
scope: "scope.record",
success() {
// 用户已经同意小程序使用录音功能,后续调用 wx.startRecord 接口不会弹窗询问
}
});
}
}
});
},
//打开设置
beginSet() {
if (wx.openSetting) {
wx.openSetting({
scope: "scope.camera",
success(errMsg) {
if (errMsg.authSetting["scope.camera"]) {
//设置授权成功,跳转拍照页
wx.redirectTo({
url: "../face/main"
});
}
}
});
} else {
wx.showModal({
title: "授权提示",
content:
"小程序需要您的微信授权才能使用哦~ 错过授权页面的处理方法:删除小程序->重新搜索进入->点击授权按钮"
});
}
},
//数据宝产品初始化 获取appKey
initProduct() {
var membershipKey = " ";//输入自己的membershipKey
var that = this;
wx.request({
url: "https://www.chinadatapay.com/MyAccount/checkMembership", // 初始化产品
dataType: "json",
method: "POST",
data: {
membershipKey: membershipKey
},
header: {
"content-type": "application/x-www-form-urlencoded"
},
success(res) {
var interfaceProductTwo = res.data.data.interfaceProductTwo;
interfaceProductTwo.forEach(item => {
if (item.interfaceId == 2061) {
var appkey = item.appkey;
that.appkey = appkey;
wx.setStorageSync("appkey", appkey);
}
});
}
});
},
uploadImage(tempFilePath) {
var appkey = this.appkey;
var that = this;
wx.uploadFile({
url: "https://file.chinadatapay.com/img/upload", // 图片上传
filePath: tempFilePath,
name: "file",
dataType: "json",
formData: {
appkey: appkey
},
success(res) {
const data = JSON.parse(res.data);
that.imageId = data.data;
that.miniAddUserInfo(); //完善用户信息
//执行回调
// return typeof callback == "function" && callback(data);
}
});
},
//点击开始录制
runRecord() {
var that = this;
wx.getSetting({
success(res) {
var recordSetting = res.authSetting["scope.record"];
var cameraSetting = res.authSetting["scope.camera"];
if (recordSetting && cameraSetting) {
that.showFaceTip = false;
that.longTip = true;
} else {
wx.showModal({
title: "授权提示",
content:
"人脸认证必须要您的微信授权才能使用哦~ 错过授权页面的处理方法:删除小程序->重新搜索进入->点击授权按钮",
success() {
if (wx.openSetting) {
wx.openSetting({
scope: "scope.camera",
success(errMsg) {
if (errMsg.authSetting["scope.camera"]) {
wx.showToast({ title: "设置成功", icon: "none" });
}
}
});
}
}
});
}
}
});
},
// 长按
handleLongPress(e) {
this.longTip = false;
this.imgsrc = "";
this.videoSrc = "";
this.startRecord(); //开始录屏
clearInterval(this.timer);
//按钮样式
this.style = "transform: scale(1.2)";
this.style2 = "transform: scale(0.5)";
this.style3 = "border: 3px solid #fb9126";
var context = wx.createCanvasContext("firstCanvas");
this.context = context;
var sysw = wx.getSystemInfoSync().windowWidth / 2;
var sysh = wx.getSystemInfoSync().windowHeight * 0.2 / 2;
var r = this.r * 1.15; //放大后半径
this.timer = setInterval(() => {
this.endDeg += this.num;
context.beginPath();
context.arc(sysw, sysh, r, 0, this.endDeg);
context.setFillStyle("white");
context.clearRect(0, 0, sysw * 2, sysh * 2);
context.setLineWidth(6);
context.setStrokeStyle("#fb9126");
context.setLineCap("round");
context.stroke();
context.draw();
}, 20);
},
//开始录像的方法
startRecord() {
this.ctx.startRecord({
success: res => {
// wx.showToast({title:'开始录制',icon:'none'})
}
});
},
//结束录像
stopRecord() {
/**问题详诉 做人脸认证需要用到小程序录个视频 视频录制结束IOS端二次调用stopRecord接口无效
* Android、IOS 首次使用此接口均可返回成功回调
* 第一次人脸录制认证识别失败后,返回视频录制页面二次人脸视频录制 IOS端在此调用stopRecord此接口无反应 Android端正常
* 多次测试发现苹果手机只有第一次使用that.ctx.stopRecord 有效,除首次外一直停留在 wx.showLoading({ title: "结束录制" });这步,任何回调均无返回
*/
wx.showLoading({ title: "结束录制" }); //IOS端除首次stopRecord有效 一直卡在此 代码无法继续往前走
var that = this;
that.ctx.stopRecord({
success: res => {
wx.hideLoading();
clearInterval(that.timer2); //关闭录制中倒计时
wx.showLoading({
title: "上传中..."
});
that.videoSrc = res.tempVideoPath;
that.imgsrc = res.tempThumbPath;
var tempFilePath = res.tempThumbPath;
that.uploadImage(tempFilePath); //获取活体照片
},
complete: function(complete) {
// console.log("complete", complete);
}
});
this.timer2 = setTimeout(
function() {
wx.hideLoading();
var imgsrc = wx.getStorageSync('imgsrc')
this.uploadImage(imgsrc);
// wx.showToast({
// title: "视频录制失败,请点击按钮拍照认证",
// icon: "none",
// duration: 3000
// });
// this.cameraBtn = false
// setTimeout(function() {
// wx.switchTab({
// url: "../index/main"
// });
// }, 3000);
}.bind(this),
8000
);
},
//拍照
takePhoto() {
wx.hideLoading();
clearInterval(this.timer2); //关闭录制中倒计时
this.ctx.takePhoto({
quality: "high",
success: res => {
var imgsrc = res.tempImagePath;
wx.setStorageSync('imgsrc', imgsrc); //将userIdEnc存入本地缓存
}
});
},
// 触摸结束
handleTouchEnd() {
if (this.longTip) return;
this.style = "";
this.style2 = "";
this.style3 = "";
clearInterval(this.timer);
// this.context.clearRect(0, 0, 200, 200); //clearRect() 方法清空给定矩形内的指定像素。
this.context.draw();
this.startDeg = 0;
this.endDeg = 0;
this.stopRecord(); //停止录像
},
//新接口 完善用户信息 接口加密方式 aes-128-cfb
async miniAddUserInfo() {
wx.showLoading({
title: "认证中..."
});
let params = JSON.parse(this.objStr);
params.imageId = this.imageId;
params.key = this.appkey;
params.client = "wxmini";
const word = JSON.stringify(params);
var key = " ";//你们自己的key
var iv = ""; //十六位十六进制数作为秘钥偏移量
var data = encrypt(word, key, iv); //加密后返回的值
try {
this.showLoading = true;
const res = await this.$post(this.$_url.miniAddUserInfo, {
data: data
});
if (res.code == 1) {
wx.hideLoading(); //关闭提示
//禁止再次发起请求
this.dBtn = true;
this.showLoading = false; //关闭加载中提示
this.content = res.msg_customer;
this.showToast = true;
// 创建账户 //token 存全局
this.globalData.is_real = true;
this.globalData.token = res.data.token;
this.globalData.user_info = res.data.user_info;
wx.setStorageSync("token", res.data.token);
wx.setStorageSync("userData", res.data.user_info);
///完成人脸识别时标记识别次数
this.setFaceNumber();
wx.hideLoading();
wx.showToast({
title: "认证成功",
icon: "success"
});
setTimeout(function() {
//实名成功
wx.switchTab({ url: "../index/main" });
}, 2000);
} else {
var msg = res.msg_customer;
wx.hideLoading(); //关闭提示
this.showLoading = false; //关闭加载中提示
wx.navigateTo({
// wx.redirectTo({
url: "../registerResult/main?msg=" + msg
});
}
} catch (error) {
wx.hideLoading(); //关闭认证中提示
this.showLoading = false; //关闭加载中提示
}
},
async setFaceNumber() {
try {
//完成人脸识别时标记识别次数;该接口没有返回值
const res = await this.$post(this.$_url.setFaceNumber, {
id_card: this.id_card
});
} catch (error) {}
}
}
};
</script>