先问个问题,大家旅游出行都遇到过哪些糟心事?大部人或多或少都有经历忘带身份证、飞机晚点、行李遗失、汽车抛锚、天气突变、乃至突发身体不适等等遭遇;然而,还有更糟糕的是到了目的地发现,遇到了“黄牛票”,一路颠沛流离,让人奔溃。
作为游客与景区之间的灰色地带,早期黄牛往往先在景区屯大量门票,然后再以更高的价格转售给游客。现在大多数景区采取身份证实名购票,在一定程度上缓解了黄牛囤票问题。但是在旅游旺季部分景区往往一票难求,黄牛便对有抢票需求的游客通过提前获取游客身份证号和姓名,采用软件脚本进行抢票,然后索要高昂的手续费。这种乱象一方面导致游客花费远超票价的资金参观景区,给游客造成经济损失;另一方面,软件抢票是否成功是一个概率问题,但是需要游客提前告知黄牛身份证号和姓名,暴露了游客隐私信息,存在较大的安全隐患。站在景区的角度来看,游客花费更多的资金购得票价本不高的门票,长此以往也会影响景区形象,不利于景区长远发展。
关注到这个问题后,在腾讯云官网上发现了“微信浮层H5”这一慧眼人脸核身SaaS产品,通过官网了解到它通过活体检测+身份证三要素(人脸、身份证号、姓名)进行用户身份验证。初步设想这一技术能够解决景区黄牛抢票问题:如果购票时需要进行活体人脸核身,那么黄牛即使拿到身份证号码和姓名,也无法购票成功。
于是我通过一个接入demo体验了它的各项功能,在接入过程中我还发现这一技术实现了一系列的安全性措施保障用户的信息安全,下面说说我的接入过程,可供有这方面需求的参考。
准备工作包括:开通人脸核身服务、业务申请、了解腾讯云慧眼人脸核身配置、获取账号的云API密钥4个步骤,下面一一详细介绍:
我们先进入腾讯云慧眼 人脸核身控制台 ,首次使用人脸核身服务的用户,需要先开通人脸核身服务。直接点击提交申请,按照实际情况填写信息,提交申请。
特别提醒:1. 互联网行业和金融行业必须上传业务相关营业资质。
因为腾讯云微信浮层H5服务不仅支持权威库比对,还支持客户自传身份证照片,所以需要的功能组合为:活体人脸核身(完成活体检测后照片与权威库比对)、活体人脸对比(完成活体检测后照片与上传照片比对)和身份信息实名验证(二要素)。
成功开通人脸核身服务后,进入自助接入页面。,在这里点击创建业务流程就能够为业务创建一个使用场景。
微信浮层H5作为腾讯云人脸核身团队“增强版人脸核身”这一产品的接入渠道,能够在官网产品介绍中了解到其特性。值得一一提的是,在这个应用场景中,黄牛就相当于系统的攻击者,腾讯云增强版人脸核身提供的设备安全增强、活体安全增强、智能分级认证增强,能够全面升级核身安全能力,据官网介绍,此产品针对摄像头劫持、恶意注入等攻击方式,拦截准确率可达99.9%。
使用时需要个人密钥,用于标识接入者身份。在腾讯云访问管理的API密钥管理页面,可以新建一组自己的密钥。
注意:所申请的API密钥需要妥善保管。
首先查看微信浮层H5配置流程。在接入微信浮层H5之前,需要完成:1.注册腾讯云账号并实名认证,2,成功申请腾讯云人脸核身。根据如下的接入时序图,整个接入过程只需要调用两个接口:1. DetectAuth获取核身入口URL(人脸核身前端入口)与认证标识BizToken ,2. GetDetectInfo获取核身结果。
微信浮层H5配置流程中详细说明了创建核身业务流程的步骤。
根据demo需求,我嘴周提交的流程如下图所示,待审核通过后,就能够通过个人账户里认证流程的RuleID使用创建的业务流程了。
审核通过后,能够在业务流程界面获取到RuleID。
demo流程如下:
1. 给游客发放一个二维码,这个二维码指向接入方调用DetectAuth的接口
2.游客使用微信扫描二维码后跳转到核身Url指定的核身H5页面,进行身份证OCR识别以及人脸识别身份核验 ,核身完成后自动调用RedirectUrl指定的获取核验结果的接入方后端接口
3. 由于腾讯云微信浮层H5后端会自动将BizToken作为参数传入RedirectUrl指定的接口,所以接入方获取结果的接口能够拿到BizToken,调用GetDetectInfo接口,获得核验结果
基于第二步的分析,我们只需要实现两个接入方后端接口即可完成腾讯云微信浮层H5方式的接入,同时为了实现通过扫描二维码启动身份核验,需要实现一个获取指向getToken接口的二维码的接口。
1. 快速接入方法
在接入过程中,我们可以充分利用官方文档的API接口范例,得到对接口的调用框架代码,只需要在里面完成自己的逻辑就行。首先在微信浮层H5配置流程页面中点击“在线调试”,进入API在线调试界面,填入必要参数,选择对应语言,就能够获取核心接入代码,直接复制到本地,适当加入业务流程代码就能直接使用。
2.demo代码
主函数中开放出三个http接口,实现如下:
func main() {
http请求路径和接口名
http.HandleFunc("/gettoken", getBizToken)
http.HandleFunc("/redirect", getResult)
http.HandleFunc("/getqrcode", getQRCode)
在IP:Port开启服务
err := http.ListenAndServe("0.0.0.0:8881", nil)
if err != nil {
fmt.Println("ListenAndServe Error:", err.Error())
}
}
三个http接口的实现如下:
getToken接口: 由游客扫码触发,调用微信浮层H5后端接口DetectAuth,获取到核身Url,供游客进行刷脸认证。传入参数包括用于指定核身流程的RuleID,以及核身结束后跳转到的购票平台前端界面的RedirectUrl(demo中为另一个获取核验结果的接口,输出游客名与核验是否成功),基于Go的实现如下:
func getBizToken(w http.ResponseWriter, req *http.Request) {
cpf.HttpProfile.Endpoint = "faceid.tencentcloudapi.com"
client, _ := faceid.NewClient(credential, "", cpf)
//实例化一个请求对象,每个接口都会对应一个request对象
request := faceid.NewDetectAuthRequest()
request.RuleId = common.StringPtr("16")
request.RedirectUrl = common.StringPtr("http://192.168.43.82:8881/redirect")
// 返回的resp是一个DetectAuthResponse的实例,与请求对象对应
response, err := client.DetectAuth(request)
if _, ok := err.(*errors.TencentCloudSDKError); ok {
fmt.Printf("An API error has returned: %s", err)
return
}
if err != nil {
panic(err)
}
// 输出json格式的字符串回包
fmt.Printf("%s", response.ToJsonString())
token := *response.Response.BizToken
url := *response.Response.Url
url = url + "&token=" + token
// 直接跳转到微信浮层h5前端进行身份认证
http.Redirect(w, req, url, 302)
}
getResult接口: RedirectUrl指定,游客在H5页面完成核身后自动跳转,传入本次核验的token和RuleID,获取核验结果。给予Go的实现如下:
func getResult(w http.ResponseWriter, req *http.Request) {
fmt.Println(req)
cpf.HttpProfile.Endpoint = "faceid.tencentcloudapi.com"
client, _ := faceid.NewClient(credential, "", cpf)
// 实例化一个请求对象,每个接口都会对应一个request对象
request := faceid.NewGetDetectInfoEnhancedRequest()
err := req.ParseForm()
if err != nil {
fmt.Println(err.Error())
}
token, found := req.Form["BizToken"]
if !found {
fmt.Println("参数解析出错")
}
request.BizToken = &token[0]
request.RuleId = common.StringPtr("16")
// 返回的resp是一个GetDetectInfoEnhancedResponse的实例,与请求对象对应
response, err1 := client.GetDetectInfoEnhanced(request)
if _, ok := err1.(*errors.TencentCloudSDKError); ok {
fmt.Printf("An API error has returned: %s", err1)
return
}
if err1 != nil {
panic(err1)
}
// 输出json格式的字符串回包
fmt.Printf("%s", *response.Response.Text)
}
getQRCode接口:获取二维码的接口实现代码如下:
func getQRCode(w http.ResponseWriter, req *http.Request) {
err1 := req.ParseForm()
if err1 != nil {
fmt.Println(err1.Error())
}
getTokenUrl, found1 := req.Form["token_url"]
if !found1 {
fmt.Println("token_url参数解析错误")
}
url := getTokenUrl[0]
w.Header().Set("content-type", "image/png")
w.Write(stringToQR(url))
// 二维码内容示例:http://192.168.43.82:8881/gettoken
}
// 字符串转二维码
func stringToQR(url string) []byte {
res, err := qrcode.Encode(url, qrcode.Medium, 256)
if err != nil {
fmt.Println(err.Error())
}
return res
}
最后在同一网段搭建测试环境,使得手机能够访问pc提供的服务(实际场景中将服务部署在公网即可),最后得到完整测试结果如下视频所示。
前往知乎浏览效果视频:zhuanlan.zhihu.com/p/587932111
在仔细阅读官网文档后,借助在线API调试工具,可以直接复制核心调用逻辑,相当顺畅地接入到逻辑代码中,整个demo实现下来,体验很好。同时,经过多次测试,都能够准确无误识别,准确率很高,再加上官网文档中所提到的一系列安全方案,可以说腾讯云微信浮层H5人脸核身能够达到景区门票购票时人脸核身的要求。