本文将为您描述使用腾讯云慧眼人脸核身服务中的微信渠道产品时(如使用人脸核身微信小程序、微信原生 H5、微信普通 H5 的人脸核身 SaaS 服务),如何与慧眼人脸核身进行对账操作。
对账工作主要分为2部分:
1. 收集使用慧眼业务时的明细信息。
2. 根据明细信息计算出账单。
下文将为您提供两种方式进行收集明细和计算账单。
方式1
在业务流程中保存明细
用户完成核验后,接入方调用 DetectAuth 接口生成的
BizToken
是一次核身流程的流水号。在业务完成后,接入方需要调用 GetDetectInfoEnhanced 接口来获取 DetectInfo
,DetectInfo
就是描述本次核身的详细信息,包括核身结果,收费详情,照片视频信息等。一个 BizToken 对应且只对应一个 DetectInfo。收集完整明细信息的关键点在于:1. 标记
BizToken
,确保不遗漏任何一个 BizToken
。
在调用 DetectAuth 接口获取 BizToken
后,必须将其存储起来,并标记该 BizToken
是否已经拉取到 DetectInfo
。2. 建立机制,确保每一个
BizToken
都能拉取到 DetectInfo
。
一般情况下慧眼侧是建议接入方在自己的回调接口中(DetectAuth 接口传入的 RedirectUrl
参数)调用 GetDetectInfoEnhanced 接口 去获取 DetectInfo
。但由于用户侧核身场景环境比较复杂,并不能保证每一次的核身流程都能回调到 RedirectUrl
。所以,接入方需要建立一个机制,来检查出未拉取 DetectInfo
的 BizToken
,并重新拉取一遍。3. 确保拉取到完成状态时的
DetectInfo
。
在人脸核身业务中,每个 BizToken
都有自己的状态,当BizToken
到达完成状态时,所有的接口均不允许调用,其对应的 DetectInfo
也不能再更新。也就是说,若 BizToken
未达到完成状态的情况下,用户有可能使用此 BizToken
进行重试。未达到完成状态的 BizToken
都须重新拉取 DetectInfo
来确保拉取到的 DetectInfo
是完成状态时的。
满足以下条件中的任意一个,即可认为 BizToken
处在完成状态:GetDetectInfoEnhanced 接口返回的
Response.Text.ErrCode
为0。距离 Token 生成时间已超过2小时。
注意
慧眼人脸核身支持配置最大可重试次数,该次数仅影响活体一比一的次数,并不影响 OCR、短信等接口的调用。
计算账单
DetectInfo
中与计费相关的信息全部都位于 Response.Text.LivenessDetail
数组中,该数组存放的是该 BizToken
进行的活体一比一的次数与每次活体一比一的详情。遍历该数组,统计 IsNeedCharge
为 true
的个数即是此 BizToken 的收费次数。注意
Response.Text.ErrCode
是用于判断本次核验是否通过的字段,不用于判断计费与否。为方便对账,建议将
LivenessDetail
数组中的每一项均保存下来。let totalCount = 0; // 活体一比一的总记录数let chargeCount = 0; // 活体一比一的收费记录数let GetDetectInfoResponse = GetDetectInfoEnhanced(xxx, xxx, ...); // 调用GetDetectInfoEnhanced接口获取DetectInfofor (let detail of GetDetectInfoResponse.Text.LivenessDetail){totalCount = totalCount + 1;if (detail.IsNeedCharge == true) {chargeCount = chargeCount + 1; // 当IsNeedCharge为true时,收费记录数加1}saveChargeDetailToDB(detail); // 保存至数据库,以便日后查看}
方式2
使用 GetWeChatBillDetails 接口每日拉取
为了方便接入方更快捷的获取明细信息,慧眼人脸核身提供了一个接口(GetWeChatBillDetails)用于拉取每日的明细信息。该接口可以拉取子账号 + RuleId 维度的某一天的所有 token 数据。
具体使用方式如下:
1. 建立定时任务,每日早上6点后开始执行。早于6点调用 GetWeChatBillDetails 接口会报参数异常。
2. 调用 GetWeChatBillDetails 接口,拉取前一天所有的验证明细信息。
let WeChatBillDetails = []; // 当日全量的账单详情let cursor = 0; // 游标位,拉取第一页时传0;剩下页面根据上一次请求回包的结果传入。let hasNextPage = true; // 是否还有下一页的标志位while (hasNextPage) { // 如果还有下一页,则继续拉取const result = GetWeChatBillDetails(Date /* 传入某一天日期*/, RuleId /* 传入RuleId*/, cursor); // 调用GetWeChatBillDetails接口,并获取返回。WeChatBillDetails = WeChatBillDetails.concat(result.WeChatBillDetails); // 将拉取到的数据合并到全量的数组中cursor = result.NextCursor; // 将回包中返回的下一页的游标赋值给游标位,准备下一次拉取hasNextPage = result.HasNextPage; // 将是否还有下一页的标志位重新赋值,用于决定是否进行下一次拉取}// 此时WeChatBillDetails中就是某一天全量的账单信息
计算账单
统计 WeChatBillDetail 数组中的 ChargeCount 总数,即为当日计费总数。同时记录 ChargeDetail 内容,可用于校验:ChargeCount 值 = ChargeDetail 中 IsNeedCharge 为 true 的条目总数 = ErrorCode 为收费错误码的条目总数。
let totalCount = 0; // 活体一比一的总记录数let chargeCount = 0; // 活体一比一的收费记录数for (let WeChatBillDetail of WeChatBillDetails) { // 遍历WeChatBillDetails数组let ChargeDetails = WeChatBillDetail.ChargeDetails; // 取计费详情属性totalCount += ChargeDetails.length; // 总记录数为计费详情的总条目数chargeCount += WeChatBillDetail.ChargeCount; // 收费记录数为ChargeCount的总和for (let ChargeDetail of ChargeDetails) {saveChargeDetailToDB(ChargeDetail); // 遍历ChargeDetails数组,保存至数据库,以便日后查看}}
常见问题
1. 什么时候进行计费上报?
计费上报时机是以一比一请求时间为准,即
Response.Text.LivenessDetail[].ReqTime
、GetWeChatBillDetails 接口中的ChargeDetail.ReqTime
。例如,BizToken 是在7月1日的23:59:59生成的,但是进行比对的时机是在7月2日的0点,那一比一的请求时间也会落在7月2日的0点,同时这次调用也会上报至7月2日的账单中。2. LivenessDetail 中有些字段为 null 是什么原因?
当本次核身没有进行一比一或者其他原因造成一比一失败时,有可能导致 ReqTime、Seq、Idcard、Name、Sim、IsNeedCharge、Comparestatus、Comparemsg、CompareLibType 字段是个空值,此时本条明细是不会进行计费的。可以理解为,只有 IsNeedCharge 字段为 true 的时候是计费的,该字段为 false、null 都不计费。
附录
GetWeChatBillDetails 接口介绍
输入参数
参数名 | 是否必填 | 类型 | 描述 |
Date | Y | Date | 拉取的日期(YYYY-MM-DD)。最大可追溯到365天前。当天6点后才能拉取前一天的数据。 |
RuleId | Y | String | 业务对应的 ruleid |
Cursor | Y | Integer | 游标。用于分页,取第一页时传0,取后续页面时,传入本接口响应中得 NextCursor 字段的值。 |
输出参数
参数名 | 类型 | 描述 |
HasNextPage | Boolean | 是否还有下一页。该字段为 true 时,需要将 NextCursor 的值作为入参继续调用本接口。 |
NextCursor | Integer | 下一页的游标。用于分页。 |
WeChatBillDetails | WeChatBillDetail 数组 | 数据,明细如下表。 |
WeChatBillDetail
属性名 | 类型 | 说明 |
BizToken | String | token。 |
ChargeCount | Integer | 本 token 收费次数。 |
ChargeDetails | ChargeDetail数组 | 本 token 计费详情,明细如下表。 |
ChargeDetail
属性名 | 类型 | 说明 |
ReqTime | String | 一比一请求时间戳,13位。 |
Seq | String | 一比一请求的唯一标记。 |
Idcard | String | 一比一时使用的、脱敏后的身份证号。 |
Name | String | 一比一时使用的、脱敏后的姓名。 |
Sim | String | 一比一的相似度。0-100,保留2位小数。 |
IsNeedCharge | Boolean | 本次详情是否收费。 |
ChargeType | String | 收费类型,比对、核身、混合部署。 |
ErrorCode | String | 本次活体一比一最终结果。 |
ErrorMessage | String | 本次活体一比一最终结果描述。 |