文档中心 > K12一脸通行解决方案IoT端侧Smile接口

支付场景-人脸app接入(刷脸/扫码)

更新时间:2021/05/06 访问次数:914

开发注意事项

  1. 接入方自动化测试/压测时,切记在人脸初始化时(install)把deviceNum设置成TEST,避免影响线上数据。上线时改回正式的deviceNum(参考3.1节第二步mockMerchantInfo):
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_DEVICE_NUM, "TEST");
  1. 接入方务必设置合适的人脸识别距离,避免误刷脸(参考3.1节第三步mockConfigInfo)
// 取值:0~1000mm,建议值:750mm
configInfo.put(ZolozConfig.KEY_ALGORITHM_MAX_DETECT_DISTANCE, 750);
  1. smile最新版本为:4.9.3.699,对应aar版本为:api-2.9.2.201120171725


1、快速接入

支付场景本地人脸app

1.1 单次刷脸

单次刷脸模式是指isv每次唤起刷脸时都需调用刷脸接口(verify),刷脸完成后人脸采集页面自动退出,常用于支付和单次核身等场景。

流程如下:

  1. isv机具端app启动时,调用刷脸SDK接口(install)传入isv和商户、gourpId信息,进行人脸和iot sdk初始化。调用register,等待初始化回调完成。register回调返回后才能进行后续刷脸。
  2. 刷脸时,isv机具端app调用刷脸SDK接口(verify):

     1)设备未进行iot授权,刷脸直接失败。

     2)设备已授权,可正常唤起人脸采集页面并进行人脸识别过程。识别完成后返回人脸识别的结果(VerifyCallback)。如果识别成功,会返回当前用户的支付宝账号信息(ftoken/uid)、比对信息(流程图第2步)

  1. 根据刷脸识别结果,isv接入方可进行相应业务逻辑(核身或者代扣)。

      对于代扣,获取ftoken后调用加签接口signWithFaceToken进行签名,提交签名到isv服务端后完成支付宝代扣流程(流程图第3步)。

1.2 扫码

扫码功能方便用户无法使用刷脸或者刷脸取消时,可以方便地切到支付宝二维码进行扫码支付。

流程如下:

  1. isv机具端app启动时,调用刷脸SDK接口(install)传入isv和商户、gourpId信息,进行人脸和iot sdk初始化(初始化过程和单次/连续刷脸是一致的,如果刷脸流程已经调用过install初始化,此处可省略)。
  2. 初始化完成后,isv机具端app可调用扫码接口(register):

     1)如果install参数未正确传入,或者isv未授权扫码功能,扫码返回失败(onEvent)。

     2)扫码成功,返回识别后的码值(onResult)。

  1. 根据扫码结果,isv接入方可进行相应业务逻辑,比如发起扣款。
  2. isv终止扫码时,可调用unregister接口停止并退出(流程图第5步)扫码。


1.3 依赖包和刷脸应用

1、业务方客户端需集成人脸apk启动器 (api-*******.aar文件),调用见《3、调用示例》。

2、机具上安装支付宝刷脸app3.0版本(smile版本号需要大于4.3.0),如smile 版本号小于4.3.0 说明为2.0版本,需要升级到3.0),目前支付(3d摄像头)和核身(双目摄像头)的smile.apk需要分开2个不同的包(根据摄像头类型(双目或者3d)选择安装对应摄像头版本的刷脸apk)。

上述集成的aar和刷脸app从项目邻客蚁上获取。


2、API说明

2.1 初始化人脸sdk

    /**
* 初始化人脸应用
*
* @param params 扩展参数,参数key为:
* {@link #MERCHANT_INFO_DEVICE_NUM}, 值类型为String,必填项
* {@link ZolozConstants#KEY_MERCHANT_INFO_ISV_NAME},值类型为String,必填项
* {@link ZolozConstants#KEY_MERCHANT_INFO_ISV_PID},值类型为String,必填项
* {@link ZolozConstants#KEY_MERCHANT_INFO_MERCHANT_ID},值类型为String,必填项
* {@link ZolozConstants#KEY_MERCHANT_INFO_MERCHANT_NAME},值类型为String,必填项
* {@link ZolozConstants#KEY_MERCHANT_INFO_MERCHANT_PAY_PID},值类型为String,必填项
* {@link ZolozConstants#KEY_GROUP_ID},值类型为String,本地模式为必填项
* @param callback 回调接口
*/
public void install(Map<String, Object> extInfo)


参数说明:

字段

参数

是否必填

具体说明

info

Map

必传参数(key定义参考ZolozConstants):

deviceNum:商户机具SN

isvPid:支付宝开发平台分配的isv pid

isvName:isv名称

merchantId:商户id(比如:学校:外标,中小学为学校统一信用编码,景区:机构代码)

merchantName:商户name(比如:学校/景区名称)

merchantPayPid:商户收款pid

(smile4.6.0以上,支付场景采用离线ftoken代扣必传)

groupID:库id

其中merchantPayPid,isv可以通过如下网址自行获取:https://opendocs.alipay.com/open/300/gb5sar

2.2 监听初始化

    /**
* 监听初始化状态
*
* @param params 扩展用,可传空
* @param callback 回调接口
*/
public void register(Map<String, Object> extInfo, InstallCallback callback)


参数说明:

字段

参数

是否必填

具体说明

extInfo

Map

扩展用,目前未用到,可传空

callback

InstallCallback

返回install成功或者失败


InstallCallback参数:

/**
* Install回调函数
*/
public abstract class InstallCallback {
/**
* 初始化结果回调函数
*
* @param smile2PayResponse 回调response,{@link Smile2PayResponse}
*/
public abstract void onResponse(Smile2PayResponse smile2PayResponse);
/**
* 初始化事件错误event回调
*
* @param code event code
* @param message event message
*/
public void onEvent(int code, String message) {
Log.w(TAG, "onEvent(): code=" + code + ", message=" + message);
}
}


onResponse回调返回smile2PayResponse,涉及的重要参数如下:

字段

类型

具体说明

code

int

取值如下:

Smile2PayResponse.CODE_SUCCESS: install成功

mExtInfo

Map<String, Object>

本地模式时,map中包括详细失败原因(FeatureResult),获取方式参考《3、调用示例》


onEvent回调code说明:

    /**
* rpc异常下载失败
*/
public static final int EVENT_CODE_NET_ERROR = -1;
/**
* rpc异常下载失败
*/
public static final int EVENT_CODE_SERVER_ERROR = -2;
/**
* 客户端内部错误:例如:startService失败等
*/
public static final int EVENT_CODE_CLIENT_INNER_ERROR = -3;
/**
* IO异常
*/
public static final int EVENT_CODE_IO_ERROR = -4;
/**
* 无存储权限
*/
public static final int EVENT_CODE_NO_PERMISSION = -5;
/**
* 客户端版本过低:服务端不支持太低的特征版本号
*/
public static final int EVENT_CODE_CLIENT_NOT_SUPPORT = -6;
/**
* 服务端下发的,人脸特征文件为空
*/
public static final int EVENT_CODE_GROUP_ABNORMAL = -7;

2.3 唤起刷脸

2.3.1 单次刷脸

    /**
* 调起人脸验证
*
* @param params
* @param verifyCallback 人脸验证回调接口{@link VerifyCallback}
* @return
*/
public void verify(final Map<String, Object> params,
final VerifyCallback verifyCallback)


参数说明:

字段

参数

是否必填

具体说明

info

Map

配置参数,参考3.1

verifyCallback

VerifyCallback

onResponse返回的结果


2.3.2 进场检测

业务方需使用api版本为:api-2.6.0.******.aar文件,smile版本为4.6.0以上;

/** 
*启动后台?脸检测(进场检测)
* @param params
* @param detectCallback ?脸检测回调{@link DetectCallback}
*/
public void detect(final Map<String, Object> params,
final DetectCallback detectCallback)

参数说明:

字段

参数

是否必填

具体说明

params

 Map

 必填参数:

LADYBIRD_ONLY_DETECT_ENTRY,设置为true

KEY_LADYBIRD_ENABLE,设置为true

detectCallback

DetectCallback

onTriggerEvent返回的结果,通知调??有?靠近或者离开

注:调用command接口可退出进场检测

2.3.3 配置参数Map

调用verify启动刷脸时,isv可根据需要传入map配置参数。所有的配置参数定义在类ZolozConfig中,主要分为以下几类:

key定义

说明

具体说明

KEY_MODE_***

业务配置

可配置刷脸模式、降级模式

KEY_ALGORITHM_***

算法配置

可配置人脸检测/活体/比对等相关参数

KEY_FACE_SEARCH_***

比对配置

可配置人脸比对相关参数

KEY_TASK_FLOW_***

流程配置

可配置串并行等相关参数,目前仅支持串行,所以连续模式时,需要设置:configInfo.put(ZolozConfig.KEY_TASK_FLOW_FEATURE_POWER_MODE, PowerMode.POWER_MOD_LOW)

参考《3、调用示例》

KEY_DEVICE_SETTING_***

相机配置

可配置相机相关参数,2D/IR双目摄像头时较常用

KEY_UI_***

刷脸UI配置

可配置刷脸UI相关参数


常用参数说明

key定义

参数说明

取值说明

KEY_MODE_FACE_MODE

业务模式,根据实际应用场景设置

默认值:FACEPAY,其他取值参考FaceMode定义

KEY_SMILE_MODE

刷脸页面显示在主屏或辅屏

默认值:主屏,参考SmileMode定义

主屏:SMILE_MODE_DEFAULT_DISPLAY

铺屏:SMILE_MODE_EXT_DISPLAY

KEY_ALGORITHM_MAX_DETECT_DISTANCE

3d摄像头检测最大距离

类型:int默认值:1000(mm)

KEY_ALGORITHM_MIN_IOD

双目摄像头检测最大距离

默认值:0.18,取值范围:0~1.0f

值越小检测距离越大

KEY_ALGORITHM_MAX_IOD

双目摄像头检测最小距离

默认值:0.45,取值范围:0~1.0f

值越小检测距离越大

KEY_FACE_SEARCH_SECURITY_LEVEL

人脸识别的阈值

类型:int 默认值:14,取值范围:0~20,

KEY_TASK_FLOW_TOYGER_POWER_MODE

串并行控制,目前仅支持串行

需设置为POWER_MODE_LOW

注:ZolozConfig还包括其他更多的参数,对于接入方理解起来成本比较高。为了降低理解成本,设置verify接口的map参数(params)时,可根据《4、业务场景配置》部分直接选取适合于自己的业务场景。


2.4 返回刷脸结果

VerifyCallback回调onResponse中返回的参数是Smile2PayResponse,定义如下:

public class Smile2PayResponse {
/**
* 人脸验证成功
*/
public static final int CODE_SUCCESS = 1000;
/**
* 人脸验证过程被中断
*/
public static final int CODE_INTERNAL_ERROR = 1001;
/**
* 人脸验证过程被用户取消操作
*/
public static final int CODE_CANCEL_BY_USER = 1003;
/**
* 人脸验证过程,用户操作超时
*/
public static final int CODE_TIMEOUT_BY_USER = 1004;
/**
* 人脸验证过程,用户重试次数过多,选择其他支付方式
*/
public static final int CODE_CHOOSE_OTHER_PAYMENT = 1005;
/**
* 人脸验证失败
*/
public static final int CODE_VERIFY_FAIL = 2006;

/**
* result code
*/
private int mCode;
/**
* face token
*/
private String mFaceToken;
/**
* sub code
*/
private String mSubCode;
/**
* sub message
*/
private String mSubMsg;
/**
* alipay user id
*/
private String mAlipayUid;
/**
* ext info
*/
private final Map<String, Object> mExtInfo = new HashMap<String, Object>();


参数说明:

字段

参数

具体说明

mCode

int

刷脸是否成功

CODE_SUCCESS:成功

CODE_CHOOSE_OTHER_PAYMENT:其他支付方式

mAlipayUid

String

支付宝uid,刷脸成功时有效

mFaceToken

String

刷脸ftoken,可用于交易,刷脸成功时有效

mSubCodemSubMsg

String

失败详细原因,刷脸失败时有效

mExtInfo

Map<String, Object>

本地模式时,刷脸返回的其他信息,包括刷脸比对结果(FaceVerifyResult)。获取方式参考《3、调用示例》





FaceVerifyResult说明:

字段

参数

具体说明

faceID

String

人脸特征唯一标示

uid

String

用户uid

securityLevel

int

比对等级

compScore

float

比对分数

compScore3D

float

3D比对分数

compScoreIR

float

IR比对分数

extInfo

Map<String, Object>

扩展用,目前为空,可忽略


2.5 中途强制退出刷脸

正常调用verify唤起刷脸过程,完成刷脸整体流程后人脸apk会自己完成关闭,无需调用该接口。如存在特殊逻辑刷脸过程中需要强制退出刷脸(如刷脸过程中判断到nfc刷卡扣款成功,需要退出人脸),则可以调用下列接口强制退出当此刷脸。

/**
* 中途强制主动退出刷脸
*
* @param params 参考{@link CommandCode}
*/
public void command(final Map<String, Object> params)


CommandCode定义如下:

public static final class CommandCode {
/**
* 退出刷脸
*/
public static final int EXIT = 0;

}

使用方式参考《3、调用示例》


2.6 监听人脸服务连接状态

极端情况下,人脸app运行过程中,由于摄像头问题、算法异常等一些无法自恢复的原因,会进行kill掉刷脸进程。为了保证正常的刷脸,isv调用方需要调用此接口进行连接状态的监听,一旦断开,需要调用方再次调用register接口。代码示例参考《3、调用示例》。

 /**
* 监听人脸service
* @param connectCallback 人脸apk连接bind/unbind回调
*/
public void setConnectCallback(ZolozConnectCallback connectCallback)

2.7 查询机具本地人脸库信息

支持总量查询和单个用户查询,使用方式参考《3、调用示例》

    /**
* 根据action查询库和用户相关信息
*
* @param action 查询action,参考{@link QueryCallback.Action}
* @param params 查询条件,key定义参考{@link QueryCallback.Param}
* @param queryCallback 结果回调,定义参考{@link QueryCallback.Result}
*/
public void query(int action, final Map<String, Object> params,
final QueryCallback queryCallback)

查询action定义如下:

    /**
* 查询action
*/
public static final class Action {
/**
* 查询人脸库信息
*/
public static final int ACTION_FACE_DB = 1;
/**
* 查询人员信息
*/
public static final int ACTION_USER_INFO = 1 << 1;
}

QueryCallback结果回调结果说明:

场景

字段

参数

具体说明

Action:ACTION_FACE_DB

查询人脸库

RESULT_FACE_DB_COUNT

String

人脸库总数

RESULT_FACE_DB_UPDATETIME

String

人脸库最近成功更新时间

RESULT_FACE_DB_UPDATE_COUNT

String

最近成功更新人脸库条数

Action:ACTION_USER_INFO

通过用户uid查询单个用户

RESULT_UID

String

用户uid

RESULT_FACE_ID

String

用户faceId

RESULT_USER_NAME

String

用户名

2.8 扫码

2.8.1 注册扫码

    /**
* 注册扫码
*
* @param params 暂时未用到,可传空
* @param scanCallback 回调接口
*/
public void register(final Map<String, Object> params,
final ScanCallback scanCallback)


2.8.2 停止扫码

    /**
* 注销,停止扫码
* @param scanCallback register设置的回调接口
*/
public void unregister(ScanCallback scanCallback)


2.8.3 返回扫码结果

public abstract class ScanCallback {
/**
* 扫码服务链接成功
*/
public static final String CODE_SUCCESS = "0";

/**
* 扫码成功返回的码值
*
* @param code 码值
*/
public abstract void onResult(String code);
/**
* 扫码服务返回的状态信息
*
* @param eventCode event码,0:扫码服务服务链接成功,其他值为失败
* @param eventMsg 错误描述
*/
public abstract void onEvent(String eventCode, String eventMsg);
}

3、调用示例

3.1 刷脸

第一步:获取Zoloz实例

import com.alipay.zoloz.smile2pay.Zoloz;

mZoloz = Zoloz.getInstance(getApplicationContext());


第二步:初始化人脸sdk

import com.alipay.zoloz.smile2pay.ZolozConstants;

mZoloz.install(mockMerchantInfo());
mZoloz.register(null, new InstallCallback() {
@Overide
public void onResponse(Smile2PayResponse smileToPayResponse) {
Log.d(TAG, "register()...response");
if (smileToPayResponse != null) {
int code = smileToPayResponse.getCode();
String msg = Smile2PayResponse.CODE_SUCCESS == code ?
"register" : "register";
showToast("code: %s, result: %s", code, msg));
if (smileToPayResponse.getExtInfo() != null) {
FeatureResult featureResult =
(FeatureResult)smileToPayResponse.getExtInfo().get(ZolozConstants.KEY_FEATURE_RESULT);
Log.d(TAG, "featureResult:" + featureResult);
}
}
}
@Override
public void onEvent(int code, String message) {
super.onEvent(code, message);
String msg = String.format("code:%d, msg:%s", code, message);
Log.i(TAG, "register.onEvent() :" + msg);
showToast(msg));
}
});

/**
* mock数据,真实商户请填写真实信息.
*/
private Map mockMerchantInfo() {
Map merchantInfo = new HashMap();
// 必填项,商户机具终端编号
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_DEVICE_NUM, "TEST");
// 必填项,ISV PID
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_ISV_PID, "TEST");
// 必填项,ISV 名称
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_ISV_NAME, "TEST");
// 必填项,商户id(团餐场景:学校id,中小学为学校统一信用编码)
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_MERCHANT_ID, "TEST");
// 必填项,商户名称(团餐场景:学校名称)
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_MERCHANT_NAME, "TEST");
// 必填项,商户支付pid(支付场景,采用离线ftoken支付时必填,需smile4.6.0以上)
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_MERCHANT_PAY_PID, "TEST");
// 必填项,库id
merchantInfo.put(ZolozConstants.KEY_GROUP_ID, "TEST");

return merchantInfo;
}


第三步:唤起刷脸

import com.alipay.zoloz.smile2pay.ZolozConfig;
import com.alipay.zoloz.smile2pay.ZolozConfig.FaceMode;
import com.alipay.zoloz.smile2pay.verify.FaceVerifyResult;
import com.alipay.zoloz.smile2pay.verify.BehaviourLog;

/**
* 调起刷脸
*/
mZoloz.verify(mockConfigInfo(), new VerifyCallback() {
@Override
public void onResponse(Smile2PayResponse smileToPayResponse) {
Log.d(TAG, "verify()...response");
if (smileToPayResponse != null) {
int code = smileToPayResponse.getCode();
String uid = smileToPayResponse.getAlipayUid();
String msg = Smile2PayResponse.CODE_SUCCESS == code ?
"识别成功" : "识别失败";
BehaviourLog behaviourLog =
(BehaviourLog)smileToPayResponse.getExtInfo().get(ZolozConstants.KEY_BEHAVIOR_LOG);
FaceVerifyResult faceVerifyResult =
(FaceVerifyResult)smileToPayResponse.getExtInfo().get(ZolozConstants.KEY_FACE_VERIFY_RESULT);
// toast显示刷脸结果,isv应按照真实场景处理和显示刷脸结果
showToast(String.format(Locale.getDefault(), "code:%s, result: %s, %s",
code, msg, JSON.toJSONString(faceVerifyResult)));
Log.d(TAG, "map:" + smileToPayResponse.getExtInfo().size());
}
}
});

/**
* mock数据,真实场景请填写实际配置.
*/
private Map mockConfigInfo() {
JSONObject configInfo = new JSONObject();
// 必填项,模式
configInfo.put(ZolozConfig.KEY_MODE_FACE_MODE, FaceMode.FACEPAY);
// 必填项,取值:0~1000mm,建议值:750mm
configInfo.put(ZolozConfig.KEY_ALGORITHM_MAX_DETECT_DISTANCE, 750);

// 可选
//configInfo.put(ZolozConfig.KEY_FACE_SEARCH_SECURITY_LEVEL, 14);
//configInfo.put(ZolozConfig.KEY_FACE_SEARCH_TOP_N, 2);

// 其他可选参数参考ZolozConfig定义
......

Map zolozConfig = new HashMap(2);
zolozConfig.put(ZolozConfig.KEY_ZOLOZ_CONFIG, configInfo.toJSONString());
// 显示在客显屏,默认主屏
// zolozConfig.put(ZolozConfig.KEY_SMILE_MODE, SmileMode.SMILE_MODE_EXT_DISPLAY);

// 设置UI config
// JSONObject uiInfo = new JSONObject();
// uiInfo.put(ZolozConfig.KEY_UI_SHOW_PAYMENT_CODE, true);
// uiInfo.put(ZolozConfig.KEY_UI_PAY_AMOUNT, 20.05f);
// uiInfo.put(ZolozConfig.KEY_UI_ENABLE_TIME_OUT, false);
// uiInfo.put(ZolozConfig.KEY_UI_SHOW_CLOCK_TIME, true);
// uiInfo.put(ZolozConfig.KEY_UI_CONFIRM_TEXT, "确认");
// zolozConfig.put(ZolozConfig.KEY_UI_CONFIG, uiInfo.toJSONString());
return zolozConfig;
}


第四步:中途强制退出刷脸

    Map<String, Object> command = new HashMap<>(2);
command.put(ZolozConfig.KEY_COMMAND_CODE, CommandCode.EXIT); // exit退出
mZoloz.command(command);


第五步:监听人脸服务连接状态

mZoloz.setConnectCallback(new ZolozConnectCallback() {
@Override
public void onConnect(boolean connected, ComponentName componentName) {
Log.d(TAG, "registerConnectCall, connected:" + connected);
if (!connected) {
mZoloz.install(mockMerchantInfo());
mZoloz.register(null, new InstallCallback() {
@Overide
public void onResponse(Smile2PayResponse smileToPayResponse) {
......
}
}
}
});

第六步:查询机具本地人脸库信息

QueryCallback queryCallback = new QueryCallback() {
@Override
public void onQuery(Map<String, Object> map) {
Log.d(JSON.toJSONString(map));
}

@Override
public void onError(int code, String message) {
}
};

// 可根据用户uid查询单个用户信息,注意区分不同Action
HashMap<String, Object> params = new HashMap<>();
params.put(Param.PARAM_UID, "2088*********");
mZoloz.query(Action.ACTION_USER_INFO, params, queryCallback);

// 可查询库总量和最近更新信息,注意区分不同Action
mZoloz.query(Action.ACTION_FACE_DB, null, queryCallback);

3.2 扫码

第一步:获取Zoloz实例

import com.alipay.zoloz.smile2pay.Zoloz;

mZoloz = Zoloz.getInstance(getApplicationContext());


第二步:初始化人脸sdk

import com.alipay.zoloz.smile2pay.ZolozConstants;

mZoloz.install(mockMerchantInfo());

/**
* mock数据,真实商户请填写真实信息.
*/
private Map mockMerchantInfo() {
Map merchantInfo = new HashMap();
// 必填项,商户机具SN
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_DEVICE_NUM, "TEST");
// 必填项,ISV PID
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_ISV_PID, "TEST");
// 必填项,ISV 名称
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_ISV_NAME, "TEST");
// 必填项,商户id(团餐场景:学校id)
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_MERCHANT_ID, "TEST");
// 必填项,商户名称(团餐场景:学校名称)
merchantInfo.put(ZolozConstants.KEY_MERCHANT_INFO_MERCHANT_NAME, "TEST");
// 必填项,库id
merchantInfo.put(ZolozConstants.KEY_GROUP_ID, "TEST");

return merchantInfo;
}


第三步:注册扫码

private void register() {
Log.d(TAG, "register()...");
if (mScanCallback == null) {
mScanCallback = new ScanCallback() {
@Override
public void onResult(String code) {
Log.i(TAG, "onResult()..." + code);
showToast("code:%s", code);
}
@Override
public void onEvent(String zcode, String msg) {
Log.i(TAG, "onError()..." + zcode + "," + msg);
showToast("zcode:%s, msg:%s", ;zcode, msg);
}
};
}

mZoloz.register(null, mScanCallback);
}


第四步:停止扫码

停止扫码时请调用下面接口,否则导致内存泄漏。

private void unregister() {
Log.d(TAG, "unregister()...");
if (mScanCallback != null) {
mZoloz.unregister(mScanCallback);
}
}

4、业务场景配置


调用verify接口启动刷脸时需要传入params参数。为了方便接入,接入方可根据自身业务场景从下面章节、选择合适的配置参数,直接copy使用即可(切记:参数值要根据实际场景进行设置)。

团餐支付场景,若为3D摄像头,强烈建议在初始化刷脸时,设置最远刷脸距离KEY_ALGORITHM_MAX_DETECT_DISTANCE750mm,以降低误将后面排队同学识别的情况;

4.1 自由支付模式

本地人脸apk的默认的支付模式。代码示例如下:

/**
* mock数据,真实场景请填写实际配置.
*/
private Map mockConfigInfo() {

JSONObject configInfo = new JSONObject();
// 必填项,模式
configInfo.put(ZolozConfig.KEY_MODE_FACE_MODE, FaceMode.FACEPAY);
// 必填项,取值:0~1000mm,建议值:750mm
configInfo.put(ZolozConfig.KEY_ALGORITHM_MAX_DETECT_DISTANCE, 750);
// 可选
//configInfo.put(ZolozConfig.KEY_FACE_SEARCH_SECURITY_LEVEL, 14);
......
Map zolozConfig = new HashMap(2);
zolozConfig.put(ZolozConfig.KEY_ZOLOZ_CONFIG, configInfo.toJSONString());

// 显示在客显屏,默认主屏
// zolozConfig.put(ZolozConfig.KEY_SMILE_MODE, SmileMode.SMILE_MODE_EXT_DISPLAY);

// 设置UI config
//JSONObject uiInfo = new JSONObject();
//uiInfo.put(ZolozConfig.KEY_UI_PAY_AMOUNT, 20.05f); <--如果需要显示金额,非必须
//uiInfo.put(ZolozConfig.KEY_UI_SHOW_CLOCK_TIME, true); <--如果需要显示时钟时间,非必须
//zolozConfig.put(ZolozConfig.KEY_UI_CONFIG, uiInfo.toJSONString());
}


4.2 定额支付模式

定额模式用于消费金额固定的场景。刷脸界面调起后一直显示,直到刷脸成功。代码示例如下:

/**
* mock数据,真实场景请填写实际配置.
*/
private Map mockConfigInfo() {
JSONObject configInfo = new JSONObject();
// 必填项,模式
configInfo.put(ZolozConfig.KEY_MODE_FACE_MODE, FaceMode.FACEPAY);
// 必填项,取值:0~1000mm,建议值:750mm
configInfo.put(ZolozConfig.KEY_ALGORITHM_MAX_DETECT_DISTANCE, 750);
// 可选
//configInfo.put(ZolozConfig.KEY_FACE_SEARCH_SECURITY_LEVEL, 14);
......
Map zolozConfig = new HashMap(2);
zolozConfig.put(ZolozConfig.KEY_ZOLOZ_CONFIG, configInfo.toJSONString());

// 显示在客显屏,默认主屏
// zolozConfig.put(ZolozConfig.KEY_SMILE_MODE, SmileMode.SMILE_MODE_EXT_DISPLAY);
......
// 设置UI config
JSONObject uiInfo = new JSONObject();
uiInfo.put(ZolozConfig.KEY_UI_ENABLE_TIME_OUT, false); <--必须设置
uiInfo.put(ZolozConfig.KEY_UI_PAY_AMOUNT, 20.05f); <--金额,必须设置
//uiInfo.put(ZolozConfig.KEY_UI_SHOW_CLOCK_TIME, true); <--如果需要显示时钟时间,非必须
zolozConfig.put(ZolozConfig.KEY_UI_CONFIG, uiInfo.toJSONString());
}


4.3 悬浮式UI模式

悬浮模式的刷脸UI是悬浮在业务方app的指定区域(刷脸UI默认:360*400px,显示在左上方,业务方可等比缩放,并指定位置显示),体验上可与业务方app合二为一,该模式可用于支付和核身场景。通过配置,支持刷脸结果页显示与否,需要注意的是:显示smile结果页时,需调用detect唤起刷脸,刷脸完成后结果回调给业务方的同时,显示结果页,调用command(Exit)可退出刷脸并销毁结果页;若不显示smile结果页,需调用verify唤起刷脸,刷脸完成直接返回结果,需业务方展示刷脸结果。

业务方需使用api版本为:api-2.5.0.******.aar文件,smile版本为4.5.0以上;

代码示例如下:

/**
* mock数据,真实场景请填写实际配置.
*/
private Map mockConfigInfo() {
JSONObject configInfo = new JSONObject();
// 必填项,模式。核身时设置其他FaceMode值
configInfo.put(ZolozConfig.KEY_MODE_FACE_MODE, FaceMode.FACEPAY);
configInfo.put(ZolozConfig.KEY_TASK_FLOW_TOYGER_POWER_MODE, PowerMode.POWER_MODE_LOW);
// 必填项,取值:0~1000mm,建议值:750mm
configInfo.put(ZolozConfig.KEY_ALGORITHM_MAX_DETECT_DISTANCE, 750);
// 可选
//configInfo.put(ZolozConfig.KEY_FACE_SEARCH_SECURITY_LEVEL, 14);
......
Map zolozConfig = new HashMap(2);
zolozConfig.put(ZolozConfig.KEY_ZOLOZ_CONFIG, configInfo.toJSONString());
// 设置UI Mode
zolozConfig.put(ZolozConfig.KEY_CAPTURE_UI_MODE, CaptureUIMode.FLOAT);

// 显示在客显屏,默认主屏
// zolozConfig.put(ZolozConfig.KEY_SMILE_MODE, SmileMode.SMILE_MODE_EXT_DISPLAY);
......
// 设置UI config
JSONObject uiInfo = new JSONObject();
// 刷脸UI在客显屏显示位置
uiInfo.put(ZolozConfig.KEY_UI_GUEST_SCREEN_RECT, new Rect(0, 0, 360, 400));
// 双屏模式,“刷脸成功结果页”在操作屏显示位置
uiInfo.put(ZolozConfig.KEY_UI_OPERATION_SCREEN_RECT, new Rect(0, 0, 360, 400))

zolozConfig.put(ZolozConfig.KEY_UI_CONFIG, uiInfo.toJSONString());

return zolozConfig;
}

4.4 进场检测模式

业务方需使用api版本为:api-2.6.0.******.aar文件,smile版本为4.6.0以上;

import com.alipay.zoloz.smile2pay.ZolozConfig;
import com.alipay.zoloz.smile2pay.ZolozConfig.FaceMode;
import com.alipay.zoloz.smile2pay.verify.FaceVerifyResult;
import com.alipay.zoloz.smile2pay.verify.BehaviourLog;

/**
* 调起刷脸
*/
mZoloz.detect(mockConfigInfo(), new DetectCallback() {
@Override
protected void onTriggerEvent(int eventCode, boolean trigger,
Map<String, Object> extInfo) {
Log.w(TAG, "onTriggerEvent() : eventCode=" + eventCode + ", trigger=" + trigger);
if (eventCode == DetectCallback.EVENT_CODE_HAS_FACE) {
mWorkHandler.post(new Runnable() {
@Override
public void run() {
if (trigger) {
showToast("检测到入场~~");
doVerify(); // 唤起刷脸:单次或者连续
} else {
showToast("检测到出场~~");
}
}
});
}
}
@Override
protected void onError(final String s, final String s1) {
showToast(s + s1);
}
});

/**
* mock数据,真实场景请填写实际配置.
*/
private Map mockConfigInfo() {
JSONObject configInfo = new JSONObject();
// 必填项,模式
configInfo.put(ZolozConfig.KEY_MODE_FACE_MODE, FaceMode.ENTRANCE);
configInfo.put(ZolozConfig.KEY_TASK_FLOW_TOYGER_POWER_MODE, PowerMode.POWER_MODE_LOW);

// 可选,2d摄像头时有用
//configInfo.put(ZolozConfig.KEY_DEVICE_SETTING_SOLUTION_WIDTH, 640);
//configInfo.put(ZolozConfig.KEY_DEVICE_SETTING_CAMERA_ID, 0);
//configInfo.put(ZolozConfig.KEY_ALGORITHM_MIN_IOD, 0.05);
//configInfo.put(ZolozConfig.KEY_ALGORITHM_MAX_IOD, 1.0);
//configInfo.put(ZolozConfig.KEY_DEVICE_SETTING_IS_MIRROR, true);
//configInfo.put(ZolozConfig.KEY_DEVICE_SETTING_ALG_ANGLE, 0);
//configInfo.put(ZolozConfig.KEY_DEVICE_SETTING_DISPLAY_ANGLE, 0);
//configInfo.put(ZolozConfig.KEY_DEVICE_SETTING_IS_DISPLAY_MIRROR, true);

// 其他可选参数参考ZolozConfig定义
......

Map zolozConfig = new HashMap(2);
zolozConfig.put(ZolozConfig.KEY_ZOLOZ_CONFIG, configInfo.toJSONString());
// 必填项
zolozConfig.put(ZolozConfig.LADYBIRD_ONLY_DETECT_ENTRY, true);
zolozConfig.put(ZolozConfig.KEY_LADYBIRD_ENABLE, true);
// 显示在客显屏,默认主屏
// zolozConfig.put(ZolozConfig.KEY_SMILE_MODE, SmileMode.SMILE_MODE_EXT_DISPLAY);

return zolozConfig;
}

5、配置参数列表

ZolozConfig包括了所有的刷脸配置参数,说明如下。参数众多,一般isv接入时参考上面章节即可完成接入工作,本章节可忽略。

/**
* ZolozConfig code sample:
*
* Map mockConfigInfo() {
* Map zolozConfig = new HashMap();
* // 采集UI模式
* zolozConfig.put(ZolozConfig.KEY_CAPTURE_UI_MODE, CaptureUIMode.ORANGE);
* // Smile模式
* zolozConfig.put(ZolozConfig.KEY_SMILE_MODE, SmileMode.SMILE_MODE_EXT_DISPLAY);
*
* // 人脸参数配置
* JSONObject configInfo = new JSONObject();
* // 业务配置
* configInfo.put(ZolozConfig.KEY_MODE_xxx, xxx);
* // 比对配置
* configInfo.put(ZolozConfig.KEY_FACE_SEARCH_xxx, xxx);
* // 算法配置
* configInfo.put(ZolozConfig.KEY_ALGORITHM_xxx, xxx);
* // 摄像头配置
* configInfo.put(ZolozConfig.KEY_DEVICE_SETTING_xxx, xxx);
* // 流程配置
* configInfo.put(ZolozConfig.KEY_TASK_FLOW_xxx, xxx);
* zolozConfig.put(ZolozConfig.KEY_ZOLOZ_CONFIG, configInfo.toJSONString());
*
* // 设置UI
* JSONObject uiInfo = new JSONObject();
* uiInfo.put(ZolozConfig.KEY_UI_xxx, xxx);
* zolozConfig.put(ZolozConfig.KEY_UI_CONFIG, uiInfo.toJSONString());
*
* return zolozConfig;
* }
*/

/**
* zoloz人脸参数配置
*/
public class ZolozConfig {

/**
* 命令,取值参考{@link CommandCode}, 默认值为{@link CommandCode#EXIT}
*/
public static final String KEY_COMMAND_CODE = "commandCode";
/**
* 采集UI模式,取值参考{@link CaptureUIMode}
*/
public static final String KEY_CAPTURE_UI_MODE = "captureUIMode";
/**
* 刷脸模式
* 值类型为int, 目前值可以为{@link SmileMode}
* 可选项,默认值为{@link SmileMode#SMILE_MODE_DEFAULT_DISPLAY}
*
* 用于控制刷脸页面显示在哪个显示屏上。
*/
public static final String KEY_SMILE_MODE = "smile_mode";
/**
* 人脸参数配置
* 下面涉及的业务配置、算法配置、比对配置、相机配置等所有配置的参数,拼成json字符串作为{@link #KEY_ZOLOZ_CONFIG}的value
*/
public static final String KEY_ZOLOZ_CONFIG = "zolozConfig";
/**
* UI配置
* 下面涉及的UI配置参数,拼成json字符串作为{@link #KEY_UI_CONFIG}的value
*/
public static final String KEY_UI_CONFIG = "uiConfig";
/**
* 高危处理方式
* 值类型为int, 目前值可以为{@link RiskDecision}
*/
public static final String KEY_RISK_DECISION = "riskDecision";

/**================================闲时上传配置================================**/
/**
* "闲时"时段的开始时刻:单位为毫秒。
*
* 该参数为long类型。默认值为:TimeUnit.HOURS.toMillis(22)
*
* 取值范围应该必须在0-24小时(转换为毫秒)之间。
*
* 如果小于0,会取其绝对值。
* 如果绝对值超过了24小时,将它对24小时(转换为毫秒)进行求模处理。
*/
public static final String KEY_IDLE_UPLOAD_START_TIME = "idleUploadStartTime";

/**
* "闲时"时段的持续时长:单位为毫秒。
*
* 该参数为long类型。默认值为:第二天早上8点(TimeUnit.HOURS.toMillis(8))- "闲时"时间的开始时刻
*
* 取值范围应该必须在0-24小时(转换为毫秒)之间。
* 如果小于0,会取其绝对值。
* 如果绝对值超过了24小时,将它对24小时(转换为毫秒)进行求模处理。
*/
public static final String KEY_IDLE_UPLOAD_INTERVAL = "idleUploadInterval";

/**
* "闲时"时段内,尝试上传的时间间隔:单位为毫秒。
*
* 该参数为long类型。默认值为:TimeUnit.HOURS.toMillis(1)
*
* 取值范围应该必须在0-1小时(转换为毫秒)之间。
* 如果小于0,会取其绝对值。
* 如果绝对值超过了1小时,将它对1小时(转换为毫秒)进行求模处理。
*/
public static final String KEY_IDLE_UPLOAD_RATE = "idleUploadRate";

/**================================业务配置================================**/
/**
* 业务模式,取值参考{@link FaceMode}, 默认值为{@link FaceMode#FACEPAY}
*/
public static final String KEY_MODE_FACE_MODE = "faceMode";

/**================================算法配置================================**/
/**
* 人脸检测区域,value:Rect
*/
public static final String KEY_ALGORITHM_ROI_RECT = "roiRect";
/**
* 保持人脸稳定时间(float),单位:s
*/
public static final String KEY_ALGORITHM_STACK_TIME = "stackTime";
/**
* 最大检测距离(深度)(int),单位:mm
*/
public static final String KEY_ALGORITHM_MAX_DETECT_DISTANCE = "maxDetectDistance";
/**
* 人脸宽度与图像宽度的最小占比(0.0f~1.0f)
*/
public static final String KEY_ALGORITHM_MIN_IOD = "minIod";
/**
* 人脸宽度与图像宽度的最大占比(0.0f~1.0f)
*/
public static final String KEY_ALGORITHM_MAX_IOD = "maxIod";

/**================================流程配置================================**/
/**
* 启用的算法能力,参考{@link Capacity}
*/
public static final String KEY_TASK_FLOW_CAPACITY = "capacity";
/**
* 检测与后续环节Power Mode设置,参考{@link PowerMode}。默认值{@link PowerMode#POWER_MODE_LOW}
*/
public static final String KEY_TASK_FLOW_TOYGER_POWER_MODE = "toygerPowerMode";
/**
* 是否换人敏感(boolean)
* true:换人时如果上一个还未完成识别,停止
*/
public static final String KEY_TASK_FLOW_CARE_FACEID_CHANGED = "careFaceIdChanged";
/**
* 是否track id敏感(boolean)
* true:识别成功后,相同track id的图像帧不执行活体和识别
*/
public static final String KEY_TASK_FLOW_CARE_RECOGNIZEDID_CHANGED = "careRecognizedIdChanged";
/**
* 是否连续自动识别(boolean)
* true:连续检测识别图像帧, false:图像帧识别成功后,停止识别
*/
public static final String KEY_TASK_FLOW_NEED_AUTO_RECOGNIZE = "needAutoRecognize";

/**================================相机配置================================**/
/**
* 预览orientation(int),取值:0,90,180,270
*/
public static final String KEY_DEVICE_SETTING_DISPLAY_ANGLE = "displayAngle";
/**
* 算法orientation(int),取值:0,90,180,270
*/
public static final String KEY_DEVICE_SETTING_ALG_ANGLE = "algorithmAngle";
/**
* 相机camera id(int)
*/
public static final String KEY_DEVICE_SETTING_CAMERA_ID = "cameraID";
/**
* 帧数据是否需要镜像(boolean)
*/
public static final String KEY_DEVICE_SETTING_IS_MIRROR = "isMirror";
/**
* 预览是否需要镜像(boolean)
*/
public static final String KEY_DEVICE_SETTING_IS_DISPLAY_MIRROR = "isDisplayMirror";
/**
* 图像帧分辨率width(int)
*/
public static final String KEY_DEVICE_SETTING_SOLUTION_WIDTH = "solutionWidth";
/**
* 相机zoom(int)
*/
public static final String KEY_DEVICE_SETTING_ZOOM = "zoom";
/**
* 用于ir摄像头,参数说明参考{@link ZolozConfig#KEY_DEVICE_SETTING_DISPLAY_ANGLE}
*/
public static final String KEY_DEVICE_SETTING_SUP_DISPLAY_ANGLE = "supDisplayAngle";
/**
* 用于ir摄像头,参数说明参考{@link ZolozConfig#KEY_DEVICE_SETTING_ALG_ANGLE}
*/
public static final String KEY_DEVICE_SETTING_SUP_ALG_ANGLE = "supAlgorithmAngle";
/**
* 用于ir摄像头,参数说明参考{@link ZolozConfig#KEY_DEVICE_SETTING_CAMERA_ID}
*/
public static final String KEY_DEVICE_SETTING_SUP_CAMERA_ID = "supCameraID";
/**
* 用于ir摄像头,参数说明参考{@link ZolozConfig#KEY_DEVICE_SETTING_IS_MIRROR}
*/
public static final String KEY_DEVICE_SETTING_SUP_IS_MIRROR = "supIsMirror";
/**
* 用于ir摄像头,参数说明参考{@link ZolozConfig#KEY_DEVICE_SETTING_IS_DISPLAY_MIRROR}
*/
public static final String KEY_DEVICE_SETTING_SUP_IS_DISPLAY_MIRROR = "supIsDisplayMirror";
/**
* 用于ir摄像头,参数说明参考{@link ZolozConfig#KEY_DEVICE_SETTING_SOLUTION_WIDTH}
*/
public static final String KEY_DEVICE_SETTING_SUP_SOLUTION_WIDTH = "supSolutionWidth";
/**
* 用于ir摄像头,参数说明参考{@link ZolozConfig#KEY_DEVICE_SETTING_ZOOM}
*/
public static final String KEY_DEVICE_SETTING_SUP_ZOOM = "supZoom";

/**================================UI配置================================**/
/**
* 支付金额(float)
*/
public static final String KEY_UI_PAY_AMOUNT = "payAmount";
/**
* 是否显示时钟时间(boolean)
* true: 显示。默认:false
*/
public static final String KEY_UI_SHOW_CLOCK_TIME = "showClockTime";
/**
* 采集页面否启用超时机制(boolean)
* false:禁用超时机制。默认:true
*/
public static final String KEY_UI_ENABLE_TIME_OUT = "enableTimeout";
/**
* 结果页超时时间(int)
* 0:不显示结果页,结果需要isv开发。> 0: 正常显示。默认:2s
*/
public static final String KEY_UI_COUNT_DOWN_TIME = "countDownTime";
/**
* 是否显示"付款码支付"按钮(boolean)
* true:显示。默认:false
*/
public static final String KEY_UI_SHOW_PAYMENT_CODE = "showPaymentCode";
/**
* "确认按钮"文本(String)
* 默认值:确认支付
*/
public static final String KEY_UI_CONFIRM_TEXT = "confirmText";
/**
* 确认页面超时时间(int)
* 单位:ms
*/
public static final String KEY_UI_CONFIRM_DISPLAY_TIME = "confirmDisplayTime";
/**
* 刷脸UI在客显屏的位置,value:Rect
*/
public static final String KEY_UI_GUEST_SCREEN_RECT = "guestScreenRect";
/**
* 刷脸UI在操作屏的位置,value:Rect
*/
public static final String KEY_UI_OPERATION_SCREEN_RECT = "operationScreenRect";

/**
* 全屏刷脸时是否显示人形框。类型:boolean, 默认false,即不显示;
* 注:只在如下三个场景生效:{@link FaceMode#ENTRANCE}, {@link FaceMode#CAPTURE}, {@link FaceMode#SIGN}
*/
public static final String KEY_UI_SHOW_BODY_OUTLINE = "showBodyOutline";

/**================================常量类定义================================**/

/**
* command code
*/
public static final class CommandCode {
/**
* 退出刷脸
*/
public static final int EXIT = 0;
/**
* 键盘按键被按下
*/
public static final int KEY_CODE = 1;
/**
* 暂停刷脸(仅预览、不检测)
*/
public static final int DETECT_PAUSE = 2;
/**
* 继续刷脸
*/
public static final int DETECT_CONTINUE = 3;
}

/**
* 采集UI模式
*/
public static final class CaptureUIMode {
/**
* 樱桃
*/
public static final int ORANGE = 0;
/**
* 全屏
*/
public static final int FULL = 1;
/**
* 悬浮
*/
public static final int FLOAT = 2;
}

/**
* 刷脸模式
*/
public static final class FaceMode {
/**
* 支付
*/
public final static String FACEPAY = "facepay";
/**
* 门禁
*/
public final static String ENTRANCE = "entrance";
/**
* 考勤
*/
public final static String SIGN = "sign";
/**
* 采集
*/
public final static String CAPTURE = "capture";
/**
* 1:1人证比对
*/
public final static String IDVERIFY = "idverify";
/**
* 闸机
*/
public final static String GATEPAY = "gatepay";
}


/**
* 算法能力
*/
public static final class Capacity {
/**
* 无效能力
*/
public static final int INVALID = 0x00;
/**
* 检测,可与其它能力结合使用
*/
public static final int DETECTION = 0x01;
/**
* 活体,可与其它能力结合使用
*/
public static final int LIVENESS = 0x02;
/**
* 抽特征,可与其它能力结合使用
*/
public static final int FEATURE = 0x04;
/**
* 比对,可与其它能力结合使用
*/
public static final int VERIFY = 0x08;
/**
* 本地MTee环境比对
* 不可与其他类型结合使用
*/
public static final int VERIFY_TEE = 0x10;
}

/**
* power mode
*/
public static final class PowerMode {
public static final int POWER_MODE_LOW = 0;
public static final int POWER_MODE_MIDDLE = 1;
public static final int POWER_MODE_HIGH = 2;
}

/**
* 刷脸mode
*/
public static final class SmileMode {
/**
* 刷脸显示在主屏幕上
*/
public static final int SMILE_MODE_DEFAULT_DISPLAY = 0;

/**
* 刷脸显示在副屏幕上
*/
public static final int SMILE_MODE_EXT_DISPLAY = 1;
}

/**
* 高危处理方式
*/
public static final class RiskDecision {
/**
* 进行辅验
*/
public static final int RISK_DECISION_VALIDATE = 0;
/**
* 按成功处理
*/
public static final int RISK_DECISION_SUCCESS = 1;
/**
* 按失败处理
*/
public static final int RISK_DECISION_FAILED = 2;
}
}

6、常见错误说明及FAQ

6.1 常见错误码说明

  • Z1065:机具没有进行iot sdk设备授权,请检查是否集成iot sdk
  • Z1050:机具本地没有人脸库,请确认register接口已经返回成功
  • Z1053:当前刷脸用户不在人脸库中。请确认扫脸用户是否已经录入人脸
  • Z1024:上一次刷脸未完成又重新发起刷脸。请确保verify/detect接口回调后,再继续调用刷脸接口
  • Z1070:刷脸服务断开。请check机具安装的smile版本号

6.2 常见错误说明

6.2.1 离线ftoken无法生成问题

  1. 确保smile版本在4.6.0及以上,api在2.6.0及以上;
  2. 商户已签约代扣和当面付功能;
  1. 确保在install和唤起刷脸方法中参数传入正确;
  2. 如果机具本来能正常生成ftoken,替换了参数(如merchantPayPid)后导致无法生成ftoken,重启机具可恢复;

FAQ

关于此文档暂时还没有FAQ
返回
顶部