关闭
公众号二维码

# K12开发文档

更新记录
版本 简要说明 修改日期
1.0 新增K12开发文档 2022/4/8

# 1. 接口规范

问题:基于平台提供的通用接口能力,服务商自由度高但缺少经验,方案落地后出现接口调用不合理、无法正常使用,代扣时序和模版不清晰,家长质疑扣错款导致客诉。

目标:指导服务商合理地使用接口能力封装方案,学校上线后避免用户链路中断或体验感极差而导致客诉。

接入规范
详情请点击进入《离线刷脸SDK商户接入规范(终端)》查阅。
详情请点击进入《离线刷脸后端接口商户接入规范(后台)》查阅。
签约/解约接入规范请查阅下述内容。

# 1.1 签约

# 1.1.1 签约后信息同步

问题1:小程序传入参数错误,用户无法进入k12官方小程序进行签约?

方案

接口文档】必须遵守如下规则:

类型 跳转类型与跳转链接必须一一对应
学校名称 必须与机构ID的学校名称一致、不能简写, 例如"深圳市高级中学"
学生信息 必须是完整班级信息(*注意传入真实班级,例如“高中一年三班”,“19届2班”等
手机号 必须满足11位,例如"15988866666"
token 有效期5分钟,注意不要过期(* 建议在跳转官方小程序前的最后一个页面,才获取token

界面提示】常见参数异常提示优化,让服务商可以自行快速地调整。

目前弹窗提示与优化后的弹窗提示分别如下图所示:

目前弹窗提示 优化后的弹窗提示

传参异常提示列表:

错误类型 文案
手机号有误 无法创建用户
传入手机号不足11位,需确保传入正确的手机号,请反馈给技术方处理。
班级信息有误 无法创建用户
班级信息不正确,需传入完整的班级信息,请反馈给技术方处理。
学校名称与机构ID不符 无法创建用户
学校名称有误,需要与机构ID对应的名称一致,请反馈给技术方处理。
token过期 无法创建用户
Token超过有效期,需确保Token获取后在5分钟内使用,请反馈给技术方处理。
类型和跳转链接不匹配 无法创建用户
传入的调用类型与跳转链接类型不一致,请反馈给技术方处理。

问题2:用户签约后,学生信息(姓名/班级/手机号)等在签约后因为换班、家长换手机等情况修改,如果没有及时同步给微信平台,会导致学生无法正常使用刷脸。
方案:当学生信息有变更时,调用用户信息修改接口、传入最新信息。

网址

# 1.1.2 签约后重新采集人脸

问题:用户签约后,因为采错照片等原因无法刷脸识别?
方案:服务商可调用重新采集接口、在学校给学生重采人脸;然后让家长打开小程序,确认重采的学生人脸照片后,系统即替换掉签约时的照片。

GET链接

# 1.2 代扣

# 1.2.1 订单补扣

问题:代扣发起时间在深夜或节假日,家长收到后质疑乱扣费,导致客诉?

接口规范建议

补扣时间不干扰家长休息
● 建议时段,对于三餐都有的学校,建议工作日早上6:00-8:00、中午11:00-14:00、晚上16:00-20:00,对于仅中午有食堂的学校,建议中午11:00-14:00;周末节假日如果学生不在校,建议不发起补扣;
● 建议频率,每笔订单每天尝试扣款最多5次,超过5次会被拦截。

公众号通知说明清晰,避免误解
● 每笔订单单独进行补扣,不建议多笔欠款合并一起扣款;
● 强调“订单延迟扣款”,与正常支付消息区分明显,避免误以为重复扣款;
● 设备断网、银行系统维护等原因也会导致扣款延误,所以避免用“欠款”字样等可能引起用户抵触的文字。
延时扣款消息与普通支付消息分别如下图所示:

延时扣款与普通支付消息

延迟原因与文案建议:

延迟原因 文案建议
零钱或银行卡余额不足 消费时“零钱或银行卡余额不足”导致扣款延误,请保持账户资金充足。
指定卡不可用 消费时“签约的银行卡被解绑”导致扣款延误,请保持银行卡可用。
无可用支付方式 消费时“无可用的银行卡导致”扣款延误,请保持银行卡可用。
垫资超过上限 消费时“微信零钱或银行卡余额不足”导致扣款延误,请保持账户资金充足。
支付凭证异常 系统异常导致扣款延迟,现已恢复。
微信账号异常 微信账号异常导致无法扣费,现已恢复。
银行卡状态异常 银行卡无法扣费导致,现已恢复。
签约异常 签约微信号解约导致无法扣款,现已恢复。

# 1.2.2 订单跨节假日支付

问题:学校放假时关闭设备,部分订单未及时上传,节后发现订单过期无法扣费?
接入规则建议
设备使用后预留1小时,等订单上传完成后,再关机或断网。
订单有效期为7天,节假日会适当延长,如果遇到订单失效,则需向平台方申请延长有效期。

# 1.2.3 大额代扣调用

问题:学校包餐制,单笔金额大于100元?
可以调用大额代扣接口:
消费额度:单笔最大额度为500元。
频率限制:教职工微信号限频为40次/月、userid为20次/月;学生的签约微信号为5次/月。

# 1.2.4 支付凭证内容展示

问题:支付凭证内容不清晰,家长不确定是否学生本人刷脸消费,导致客诉核实?
接口规范建议:扣费内容信息要具体、清晰,避免家长疑惑。

内容要求 举例
必备内容 展示消费者姓名、消费场所 王小明-中午食堂就餐
王小明-面包房消费
进阶内容 展示具体档口,菜品/商品信息 王小明-中午食堂6号档口消费,两荤一素套餐
王小明-便利店消费,酸奶

样式示例:

示例样图

# 1.3 解约

# 1.3.1 解约后重新签约

问题:微信号冻结/丢失等原因,无法还款、导致无法再使用刷脸代扣?
指导服务商获取还款链接,让用户通过其他微信号还款,然后通过后台接口进行解约,让用户使用其他微信号重新签约。
● 还款链接:服务商后台获取垫资的还款链接、线下向用户核实后,人工转发给还款的微信号;
重新签约1

● 后台解约:服务商调用后台解约接口进行解约。

重新签约2

# 1.3.2 毕业批量解约

问题:毕业季学生家长未解约,服务商如何清理数据?

● 后台解约:调用后台解约接口,服务商获知毕业学生名单后,可以对毕业学生进行批量解约,注意控制调用解约接口的频率。

批量解约

# 2. 签约小程序

跳转一共包含3种场景,签约集采照片确认重采照片

跳转方式:详情请点击wx.navigateToMiniProgram查看。

场景1:集采照片

主要用于学校统一采集学生照片场景,目的是为了提高签约效率,实现录入照片的操作。

wx.navigateToMiniProgram({
	appId:'wx5931af4836330935', //采集小程序appid
	path:'/pages/face_take_photos/take_photos?is_first=1', //小程序路径
	extraData: {
		type:'take_photo',//采集跳转
		user_name: '张三',   //刷脸用户姓名
		school_name:'深圳中学', //学校
		user_type:'STAFF', //职业(STUDENT:学生,STAFF:职员)
		student_info:{'class_name':'1班'}, //class_name:班级,user_type为STUDENT时必传
		staff_info:{'occupation':'教师'}, //occupation:职业, user_type为STAFF时必传
		school_list:["深圳中学", "宝安中学"],// 学校列表,至少包含本学校
		organization_id: 'O1947FD2089aed8785', //organazition_id
		out_user_id: 'test',  // out_user_id,商户侧的用户ID,唯一不可重复
		account:'15988866666', // 签约手机号
		token:'XCXab19673d0d0b5c0ffd980fb60ce82f5e', //商户认证凭据
	},
	envVersion: 'trial',    // 如果要跳转体验版,加上这个参数,否则请不要加这个参数
	success(res) {
		// 成功跳转到签约小程序
	},
	fail(res) {
		// 未成功跳转到签约小程序
	}
})
字段 描述 示例 必填
type 跳转类型 固定值:take_photo
user_name 用户名 张三
school_name 学校名称 深圳中学
user_type 职业
STUDENT:学生
STAFF:职员
STUDENT
student_info 学生信息 {'class_name':'高一(1)班'} user_type为STUDENT时必填
staff_info 职工信息 {'occupation':'教师'} user_type为STAFF时必填
school_list 学校列表 ["深圳中学", "宝安中学", "南山中学", "罗湖中学"]
organization_id 机构id O1947FD2089aed8785
out_user_id out_user_id test
account 手机号 15988866666
token token XCXab19673d0d0b5c0ffd980fb60ce82f5e

referrerInfo字段说明

{
	appId:'wx5931af4836330935', //采集小程序appid
	extraData:{
		'return_code':'SUCCESS',  //状态码
		'return_msg':'录入成功',   //提示信息
	}
}
已录入 有照片,且转码成功,照片质量合格 SUCCESS 录入成功
未录入 无照片 FAIL 未录入

场景2:签约

签约正常流程,如果已有集采的照片,在签约时会展示已经录入的照片,否则有录入照片的流程。

wx.navigateToMiniProgram({
	appId:'wx5931af4836330935', //小程序id
	path:'/pages/face_index/index?is_first=1', //小程序路径
	extraData: {
		type:'sign',//签约跳转
		user_name: '张三',   //刷脸用户姓名
		school_name:'深圳中学', //学校
		user_type:'STAFF', //职业(STUDENT:学生,STAFF:职员)
		student_info:{'class_name':'1班'}, //class_name:班级,user_type为STUDENT时必传
		staff_info:{'occupation':'教师'}, // occupation:职业, user_type为STAFF时必传
		school_list:["深圳中学", "宝安中学"],// 学校列表,至少包含本学校
		organization_id: 'oea567edbgADeG', // 机构ID
		out_user_id: 'SEGdget123987789',  // 商户侧用户ID
		account:'15988866666', // 签约手机号
		token:'PRESIGN_DGET1233543djgegeedde'
	},
	success(res) {
		// 成功跳转到签约小程序
	},
	fail(res) {
		// 未成功跳转到签约小程序
	}

})
字段 描述 示例 必填
type 跳转类型 固定值:sign
user_name 用户名 张三
school_name 学校名称 深圳中学
user_type 职业
STUDENT:学生
STAFF:职员
STUDENT
student_info 学生信息 {'class_name':'高一(1)班'} user_type为STUDENT时必填
staff_info 职工信息 {'occupation':'教师'} user_type为STAFF时必填
school_list 学校列表 ["深圳中学", "宝安中学", "南山中学", "罗湖中学"]
organization_id 机构id O1947FD2089aed8785
out_user_id out_user_id test
account 手机号 15988866666
token token XCXab19673d0d0b5c0ffd980fb60ce82f5e

referrerInfo字段说明

referrerInfo字段说明 {
	appId:'wx5931af4836330935',
	extraData:{
		'return_code':'SUCCESS',
		'return_msg':'签约成功',
	}
}
签约成功 SUCCESS 签约成功
签约失败 FAIL 签约失败

场景3:家长确认学生重采照片(低频)

只要用户学生照片质量不合格,就需要重新录入照片,家长进行确认后即可使用新的照片刷脸消费。

跳转k12小程序参数字段

wx.navigateToMiniProgram({
	appId:'wx5931af4836330935', // 确认小程序appid
	path:'/pages/photo_confirm_user/photo_confirm_user',//小程序路径
	extraData: {
		type:'confirm_register_photo',// 家长确认学生重采照片场景
		user_name: '张三',   // 刷脸用户姓名,学生名字
		school_name:'深圳中学', // 学校
		user_type:'STAFF', //职业(STUDENT:学生,STAFF:职员)
		organization_id: 'O1947FD2089aed8785', // 机构ID
		out_user_id: '516064415', // 商户的用户ID
		account:'15988866666', //签约手机号
		token:'XCXab19673d0d0b5c0ffd980fb60ce82f5e'
	},
	envVersion: 'trial',    // 如果要跳转体验版,加上这个参数,否则请不要加这个参数
	success(res) {
		// 成功跳转到小程序确认流程
	},
	fail(res) {
		// 未成功跳转到小程序确认流程
	}
})
字段 描述 示例 必填
type 跳转类型 固定值:confirm_register_photo
user_name 用户名 张三
school_name 学校名称 深圳中学
user_type 职业
STUDENT:学生
STAFF:职员
STUDENT
school_list 学校列表 ["深圳中学", "宝安中学", "南山中学", "罗湖中学"]
organization_id 机构id O1947FD2089aed8785
out_user_id out_user_id 516064415
user_id user_id FU29EAEFZ5722adadd
account 手机号 15988866666
token token XCXab19673d0d0b5c0ffd980fb60ce82f5e

跳转回商户小程序携带参数

referrerInfo字段说明 {
	appId:'wx5931af4836330935', // 商户小程序appID
	extraData:{
		'return_code':'SUCCESS',
		'return_msg':'确认成功',
	}
}
确认成功 SUCCESS 确认成功
确认失败 FAIL 确认失败

# 3. 终端接入

更新记录
版本 简要说明
2.12.100 initWxpayface 调⽤必有回调,如果失败,可以等待⼀段时间处理;
加⼊need_ext_verify 来判断是否需要辅助验证;
补充摄像头散热问题软件建议。
2.12.200 增加preloadSdkEnv接⼝来减少启动识别耗时;
旧有的K12UserInfo改名为UserInfo,新旧版本AAR都能兼容现有apk,商户不需要单独考虑兼容性问题;
startVerify增加“用户信息更新中,请等待...”的271378645错误码;
startVerify根据need_ext_verify来判断是否辅助验证,后续不再保证只根据个数来做处理。
2.12.704 辅助验证要求下调,刷脸环境恶劣可以降级后四位验证;
辅助验证策略必须改造2.0版本need_ext_verify 才能适配新版,否则finishFaceVerify会提示”请输入⼿机号后四位“的271378652错误;
增加getUserInfo接口,方便商户确认机器用户信息是否同步以及签约状态ge'tSdkInfo数量显示的是全部用户数量,历史版本仅显示采集照⽚成功的⽤户数量。
2.13.808 getUserInfo会同步返回用户信息更新时间和同步到设备时间。
2.21.300 推荐预览大小是3:4的高宽比;
数据库初始化失败271378588错误;
通用系统错误271378694;
双胞胎问题处理与解决;
预览接口提供手动移除可能性。

# 3.1 常用参考

请参考《刷脸Android SDK接入指南》

# 3.2 业务流程

业务流程

# 3.3 注意点

A、流程1、流程2任选其一即可;
B、使用“流程1”耗时可以更优,适用于支付金额在开始识别之前就已知的情况;
C、使用“流程2”耗时可以更长,适用于支付金额在开始识别之前未明确的情况;
D、展示完用户信息后,获取支付凭证和用户点击确认可以并行处理,优化支付耗时。

# 3.4 使用说明

使用方式
A、安装人脸App;
B、商户接入人脸SDK。

注意点
A、商户使用SDK接口均封装在WxPayFace类中,该类以单例形式存在。调用结果统一由IWxPayfaceCallback回调;
B、参数或回调结果以Map形式传递,方便扩展,具体字段名称及返回值定义参考文档;
C、每次SDK退出(release或异常),如果重新调用任何其它api,都会重新调用init,并且回调之前的callback,这里建议init的callback固定为同⼀个,可以持续监听对应的回调事件。

//IWxPayfaceCallback//继承⾃AIDL接⼝,⽅便服务商使⽤。⽬前仅提⼀个统⼀的回调接⼝。
public abstract interface IWxPayfaceCallback {
	public abstract void response(Map info) throws RemoteException;
}

# 3.5 通用请求参数(每个请求都需要带)

经过“初始化”,“获取rawData”、“销毁并释放资源” 步骤外的所有流程都需要带授权凭据和商户基础信息。

请求参数 必填 类型 说明
authinfo string 调用授权凭据
appid string 微信公众号
sub_appid string 子商户公众账号id(非服务商模式不填)
mch_id string 填您的商户号
mch_name string 商户名
sub_mch_id string 子商户号(非服务商模式不填)
organization_id string 机构id

# 3.6 通用返回参数(每个请求都会回应)

当商户刷脸APP向微信离线刷脸SDK请求时,都会返回通用的参数。

变量名 必填 描述 解决方案
return_code 错误码
return_msg 错误描述 展示错误原因
err_code 二级错误码类型Integer,注意判空 错误码,有特定的规则说明
return_code 描述 解决方案
SUCCESS 接口成功
ERROR 接口错误 展示错误原因(该请求无法通过重试解决)
PARAM_ERROR 参数错误 参照错误提示
SYSTEMERROR 接口返回错误 系统异常,建议提示让用户重试
FAIL 接口失败 SDK服务连接断开,SDK会自动重试请求

# 3.7 通用err_code

通用err_code(注意判空,不⼀定返回,只用于辅助查问题作归因,不存在的时候可以使用return_msg直接归因)。

通用err_code 描述 解决方案
271378620 刷脸服务未初始化(所有接口都有可能返回) 等待500ms左右调用init
271378621 刷脸服务初始化中(所有接口都有可能返回) 等待500ms左右调用init
271378498 通用输入参数错误 无,检查api调用
271378562 机构ID不对 无,检查api调用
271378434 sn不匹配 无,检查api调用
271378525/271378435/271377920 authinfo异常 重新获取authinfo
271378588 数据库初始化失败 建议检查调用release时机;release时间无异常则检查设备存储,重新初始化
271378694 系统异常 建议release后初始化重试

# 3.8 常规接口

(1)初始化(initWxpayface)
接口作用:对人脸SDK进行初始化

public void initWxpayface(Context ctx,Map info, IWxPayfaceCallback callback);

请求参数(无通用参数)

请求参数 必填 类型 说明
ip string HTTP代理IP
port string HTTP代理端口,需为数字
user string HTTP代理的用户名
passwd string HTTP代理的密码

返回参数
无特殊参数,只有returncode和returnmsg

示例

private void initPayFace() {
	Map<String, String> m1 = new HashMap<>();
	m1.put("ip", "xxx.xxx.xxx.xxx");
//若没有代理,则不需要此行,代理ip请自行寻找
	m1.put("port", "8888");
//若没有代理,则不需要此行,代理端口不一定是8888,根据代理设置来决定
	WxPayFace.getInstance().initWxpayface(this, m1, new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return ;
			}
			String code = (String) info.get("return_code");
			String msg = (String) info.get("return_msg");
			Log.d(TAG, "response info :: " + code + " | " + msg);
			if (code == null || !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息: " + msg).printStackTrace();
				return ;
			}
			Log.d(TAG, "调用返回成功");
			/*
			在这里处理您自己的业务逻辑
			*/
		}
	});
}

建议
A、您可以自定义一个Application,然后在自定义Application的onCreate()中调用initPayFace()完成人脸识别模块的初始化;
B、您可以只在被调用人脸识别模块的activity的onCreate()中完成initPayFace()的调用;
C、失败或者超时请release后重试。

(2)获取数据(getWxpayfaceRawdata)

public void getWxpayfaceRawdata(IWxPayfaceCallback callback);

请求参数
无参数

返回参数(包含returncode和returnmsg)

额外参数 必填 类型 说明
rawdata string(2048) 初始化数据,用于API(获取调用授权凭据authinfo)

示例

private void getWxpayfaceRawdata() {
	WxPayFace.getInstance().getWxpayfaceRawdata(new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("returncode");
			String msg = (String) info.get("returnmsg");
			String rawdata = (String)info.get("rawdata");
			if (code == null || rawdata == null || !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
				return ;
			}
			/*
			在这里处理您自己的业务逻辑
			*/
		}
	});
}

建议:失败或者超时请重新release。

(3)获取调用授权凭据authinfo

接口定义

POST https://api.mch.weixin.qq.com/v3/offlineface/authinfo

请求参数

字段名 变量名 类型 必填 示例 说明
服务商appid sp_appid string 示例值: wx369ab4160391b078
字符长度限制: [1, 32]
商户appid
子appid sub_appid string 有则必传 示例值: wx369ab4160391b078
字符长度限制: [0, 32]
子商户appid
子商户号 sub_mchid string 示例值: 1900000109
字符长度限制: [0, 32]
子商户号
设备id device_id string 示例值: TXAP12029003744ND002112
字符长度限制: [1, 32]
终端设备唯一ID,必须为数字、字母、下划线的组合
原始数据 raw_data string 示例值: kh5HJYlzqXosbqJCOYXASBxYozukRFjg5P9MY
字符长度限制: [1, 2048]
初始化数据,由微信人脸SDK的接口返回。
机构id organization_id string 示例值: OCAABBDDee
字符长度限制: [1, 64]
机构ID,注意创建机构的商户号和mch_id应该保持一致

返回结果

字段名 变量名 类型 必填 示例 说明
授权信息 authinfo string 示例值: kh5HJYlzqXosbqJCOYXASBxYozukRFjg5P9MY
字符长度限制: [1, 4096]
SDK调用凭证,用于调用SDK的人脸识别接口

请求示例

<return_code>SUCCESS</return_code>
<return_msg>请求成功</return_msg>
<nonce_str>Tivppi4UXAbgLxk8e1Sij76YdowOFFii</nonce_str>
<sign>PL0EUID6A7ICWNKHCSMQC0UIXOYNSE5B</sign>
<appid>wx31fdaErqR31</appid>
<mch_id>12345689</mch_id>
<authinfo>q3OPhFtQBf6KZGqmZhejKCRy5K/ch0kwS11YSsEj9XmUGqcsT2QPHt0Oa7xaCMCoSZTWMmShCo4dOiO5tU+OJEsvSxXzn5m3Nkh747tinNlbpJmVq1zOPj+FJNndkzanxoiAddO8p1EfrmUhJs/aNf0pDfrPoVfkAapK+ZY6blwyaDQ9bB7+KkZq29kObsXOZ3thg+bxP4RAqC0oxNS4JiyP0uA1Euzxtkc9lCTebloFied8stILrMehUKukeMGkZ1SzTyc8/HFHApzHahNPX6yD8ttzYnhe+IRMFJgpuTlIvEOYZUxenPXE1A5clrPvOBeJDszX/OvZl4fpYWPpXAcVQlw+gfYhblt+rT6ALMsD73w/rT4NRriQEEraC4Pfb5yua4qAqv4TVo04</authinfo>
<expires_in>3600</expires_in>

建议:返回的接口凭证authinfo,可以在expires_in指定的有效期内,同一台机具上重复使用。

注意:authinfo有效期一般是36个小时,建议设备自动每小时更新一次。

(4)销毁并释放资源(releaseWxpayface)

public void releaseWxpayface((Context cxt);

请求参数
无参数

返回参数
无参数

示例

private void releasePayFace() {
	WxPayFace.getInstance().releaseWxpayface(this);
}

注意:获取rawdata和authinfo失败或者超时时,调用此接口,即release后重试。

(5)手动更新人脸库(manualUpdateFaceDatas)

public void manualUpdateFaceDatas(Map info,IWxPayfaceCallback cb);

请求参数
包含通用请求参数

返回参数(包含通用返回参数和通用errCode)
如果returncode不为成功,可以使用返回的returnmsg,比如“正在更新中...” 可能返回errcode 271378620 和 271378621,具体处理方式参考errcode说明。

示例

private void manualUpdateFaceDatas() {
//params包含请求通用参数(authinfo,mch_id等)
	WxPayFace.getInstance().manualUpdateFaceDatas(params,new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("return_code");
			String msg = (String) info.get("return_msg");
			if (code == null || !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
				return ;
			}
		}
	});
}
}

注意
A、商户app启动必须调用更新人脸库;
B、SDK有自身的自动更新逻辑,但是没有回调,适用于同步少量数据的时间,比如商户就餐期间等;
C、手动更新同步存在回调,适用于同步大量数据的时间,比如商户就餐前登录账号的时间,保证数据尽快同步到本地,使用时希望能设置loading页面,禁止用户操作,必须等待回调再开始操作;
D、自动更新同步在网络良好的情况下一般要前端修改用户信息3分钟左右,手动更新会更快一些,并且适用于机器重置数据后同步恢复数据状态。
同步的原因主要是是增加新用户信息;对删除用户出库;更新用户状态(比如调整欠费状态、是否禁用等)。

(6)预加载识别资源(preloadSdkEnv)

public void preloadSdkEnv(Map info,IWxPayfaceCallback cb);

说明
一般情况下,应用启动后的第一次调用开启摄像头等api会耗时较长,因为涉及到SDK的初始化工作,涉及到很多io读写,如果人脸库规模越大,初始化时间越长,如果提前preloadsdkenv加载资源,可以保证第一次开启摄像头和识别启动很快。

请求参数
包含通用请求参数

返回参数(包含通用返回参数和通用errCode)
无特殊参数,只有returncode和returnmsg,可能返回errcode 271378620 和 271378621,具体处理方式参考errcode说明。

示例

private void preloadEnv() {
//params包含请求通用参数(authinfo,mch_id等)
	WxPayFace.getInstance().preloadSdkEnv(params,new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("return_code");
			String msg = (String) info.get("return_msg");
			if (code == null || sdkVersion == null || !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
				return ;
			}
			/*
			在这里处理您自己的业务逻辑
			*/
		}
	});
}

(7)获取支付SDK相关信息(getSdkInfo)

public void getSdkInfo(Map info,IWxPayfaceCallback cb);

请求参数
包含通用请求参数

返回参数(包含通用返回参数和通用errCode)

返回参数 必填 类型 说明
sdk_version string(2048) 支付app版本
face_feature_version string(2048) 人脸特征版本
user_info_total_count int 数据库全部用户信息数量,包含小程序图片未确认的用户信息
user_info_dbcount int 小程序图片已确认的数据库用户信息数量
user_info_memcount int 小程序图片已确认能检索到的用户信息数量

非通用错误码

无特殊参数,只有returncode和returnmsg,可能返回errcode 271378620 和 271378621,具体处理方式参考errcode说明。

示例

private void getSdkInfo() {
//params包含请求通用参数(authinfo,mch_id等)
	WxPayFace.getInstance().getSdkInfo(params,new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("return_code");
			String msg = (String) info.get("return_msg");
			String sdkVersion = (String)info.get("sdk_version");
			String faceFeatureVersion = (String)info.get("face_feature_version");
			int faceFeatureVersion = (Integer)info.get("user_info_dbcount");
			if (code == null || sdkVersion == null ||
			        !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
				return ;
			}
			/*
			在这里处理您自己的业务逻辑
			*/
		}
	});
}

(8)获取用户信息状态(getUserInfo)

public void getUserInfo(Map info,IWxPayfaceCallback cb);

用途
落地排查问题专用,商户需要获取用户信息在机器上的同步状态,避免因为同步而导致的无法交易问题。

请求参数

特殊参数 必填 类型 说明
out_user_id string 用户在商户处的唯一id,商户需保持唯一性,如果不唯一,终端返回检索到的第一个

返回参数(包含通用返回参数和通用errCode)

特殊参数 必填 类型 说明
status string 用户当前状态为空表示不存在;
用户当前状态FS_NORMAL代表正常可用;
用户当前状态为其他,表示用户无法支付
update_time string 用户信息更新时间,格式yyyy-MM-dd HH:mm:ss
sync_time string 用户信息同步到本地时间,格式yyyy-MM-dd HH:mm:ss

示例

private void getUserInfo() {
//params包含请求通用参数(authinfo,mch_id等)
	WxPayFace.getInstance().getUserInfo(params,new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("return_code");
			String msg = (String) info.get("return_msg");
			if (code == null || !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
				return ;
			}
			final String status = (String) info.get(FacePayConstants.KEY_RET_FACE_FEATURE_STATUS);
			final String syncTimeStr = (String) info.get(FacePayConstants.KEY_RET_USER_SYNCTIME);
			final String updateTimeStr = (String) info.get(FacePayConstants.KEY_RET_USER_UPDATETIME);
			String result = TextUtils.isEmpty(status) ? "用户不存在" : "用户当前状态:" + status;
		}
	});
}
}

(9)设置预览view(setCameaPreview)

public void setCameaPreview(SurfaceView surfaceView,Map info,IWxPayfaceCallback cb);

请求参数
包含通用请求参数

特殊参数 必填 类型 说明
surfaceView surfaceView 摄像头回调展示界面,默认渲染高度使用surfaceView高宽

返回参数(包含通用返回参数和通用errCode)

可能返回errcode 271378620 和 271378621,具体处理方式参考errcode说明。

示例

private void setCameaPreview(SurfaceView surfaceview) {
//params包含请求通用参数(authinfo,mch_id等)
	WxPayFace.getInstance().setCameaPreview(surfaceview,params,new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("return_code");
			String msg = (String) info.get("return_msg");
			if (code == null || !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
				return ;
			}
		}
	});
}
}

注意
A、预览view主要是用于摄像头的图像画面回调,必须保证surface一定不能为空;
B、如果绑定的surfaceview调用surfaceDestroyed销毁后,记得需要重新绑定。

(10)移除预览view(removeCameaPreview)

public void removeCameaPreview(SurfaceView surfaceView,Map info,IWxPayfaceCallback cb);

注意
预览界面默认可以自行进行绑定和移除,特殊的surfaceview可以考虑自行移除预览view。

请求参数
包含通用请求参数

返回参数(包含通用返回参数和通用errCode)
可能返回errcode 271378620 和 271378621,具体处理方式参考errcode说明。

示例

private void removeCameaPreview(SurfaceView surfaceview) { //params包含请求通用参数(authinfo,mch_id等)
	WxPayFace.getInstance().removeCameaPreview(surfaceview,params,new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("return_code");
			String msg = (String) info.get("return_msg");
			if (code == null || !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
				return ;
			}
		}
	});
}
}

(11)开始识别(startVerify)

public void startVerify( Map info, IWxPayFaceCallbackAIDL cb);

请求参数
包含通用请求参数

返回参数(包含通用返回参数和通用errCode)
可能返回errcode 271378620 和 271378621,具体处理方式参考errcode说明。

特殊返回参数 必填 类型 说明
user_info_list UserInfo 类型 识别后返回的用户信息,返回多个则需要商户处理手机号辅助校验,注意用户信息此时不包含userId
best_face_img Bitmap类型 安全处理后的现场图片,避免用户信息泄漏
best_face_rect_left float 0-1之间,表明人脸的最左边
best_face_rect_right float 0-1之间,表明人脸的最右边
best_face_rect_top float 0-1之间,表明人脸的最上边
best_face_rect_bottom float 0-1之间,表明人脸的最下边
err_code Integer 人脸识别异常原因,比如人脸未录入、请摘掉口罩等,重点注意-6是“未检测到人脸”
return_msg String err_code对应异常原因
need_restart_verify boolean false表示会自动重新识别,true需要手动恢复
need_ext_verify boolean 2.23版本开始支持;
是否需要额外的辅助验证,相比userinfolist是为了方便后续拓展,新版本都采用这个参数判断是否需要验证手机号
face_verify_id string 用于定位问题的唯一id

特殊的return_code

特殊的return_code 说明 描述
FIRST_FRAME_CALLBACK 识别后第一帧回调了 商户可以配合去做cameraview的展示,如果不需要根据这个信息处理surfaceview的可以不做处理

二级错误码参考

错误码 描述 是否停止识别(默认否)
-1 请往前移一点
-2 请保持脸部在正中央
-3 请往后移一点
-5 请保持脸部端正
-6 未检测到人脸 否,商户可以自己关掉
-10 请将人脸移至画面正中央
-11 请右移至画面中央
-12 请左移至画面中央
-13 请将人脸移至画面正中央
271377935 请摘掉眼镜或帽子
271377936 请不要遮挡面部
271378510 请与设备保持合适距离
271378511 请面向摄像头刷脸
271378526 未识别出你的身份
271377938 识别中...
27137846、27137846、
27137846、27137858、
27137858、27137858、
27137859、27137859、
271378592
摄像头状态异常,请重启
271378645 设备无法使用,请等待用户信息更新完成

其它异常问题可以直接参考接口返回的异常信息来做展示,needrestart

public class UserInfo implements Parcelable {
	private String userId;
	private String outUserId;
	private String status;
	//用户状态,FS_NORMAL为正常,其余非法,不能扣款
	...
}

示例

private void startVerify() {
//params包含请求通用参数(authinfo,mch_id等)
	WxPayface.getInstance().startVerify(params,new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("return_code");
			String msg = (String) info.get("return_msg");
			if (code == null || !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息,return_msg:" + msg + "   ").printStackTrace();
				return ;
			}
			List<UserInfo> userInfos =(List<UserInfo>)info.get("user_info_list");
//是否需要辅助验证
			final Boolean needExtVerify = (Boolean) (info.get(FacePayConstants.KEY_RET_PARAMS_NEED_EXT_VERIFY));
			final Bitmap bitmap =(Bitmap)info.get("best_face_img");
			Handler handler = new Handler(Looper.getMainLooper());
			handler.post(new Runnable() {
				@Override
				public void run() {
					mImageView.setImageBitmap(bitmap);
					mImageView.requestLayout();
				}
			});
		}
	});
}

注意
A、识别接口分为开启和停止,识别成功后会自动停止;
B、识别失败会自动重新开启,并返回对应的错误信息,注意271378467/271378468/271378469的返回码;
C、识别成功返回的userInfo类型,记得在proguard里需要keep对应的class -keep class com.tencent.wxpayface.data.UserInfo{ *; };
D、startVerify后成功流程应该是finishverify->getFacePayCredential;如果中途异常退出需要调用stopVerify,流程只支持串行,并行会提示271378531 ,上次识别未完成

返回参数有提供人脸识别框的坐标范围,主要优化现场照有多个人脸存在的场景,请商户自己考虑勾选框对应的颜色问题。

(12)停止识别(stopVerify)

public void stopVerify(Map info,IWxPayfaceCallback cb);

请求参数
包含通用请求参数

返回参数(包含通用返回参数和通用errCode)

可能返回errcode 271378620 和 271378621,具体处理方式参考errcode说明。

示例

private void stopVerify() {
//params包含请求通用参数(authinfo,mch_id等)
	WxPayFace.getInstance().stopVerify(params,new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("return_code");
			String msg = (String) info.get("return_msg");
			if (code == null || !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
				return ;
			}
		}
	});
}
}

注意
任意时刻都可以调用该接口,但是注意该接口调用后并不会清除上一次的识别数据,仍然可以走完支付流程

(13)完成识别流程( finishFaceVerify)

public void finishFaceVerify(Map info,IWxPayfaceCallback cb);

请求参数
包含通用请求参数

特殊必填 类型 说明
user_phone string

返回参数(包含通用返回参数和通用errCode)
可能返回errcode 271378620 和 271378621,具体处理方式参考errcode说明。

返回参数 必填 类型 说明
user_info UserInfo的parcelable类型 返回完成识别流程的用户信息,这里的userinfo会带有userId
face_verify_id string 用于定位问题的唯一id

二级错误码参考

error_code return_msg 说明
271378532 传入的手机号错误,请联络客服 无满足条件用户返回
271378652 传入验证信息确认,请联络客服 新版SDK需要根据need_ext_verify判断是否需要输入手机号
271378587 输入的手机号匹配到多个用户,请联系客服 存在同一个手机尾号人脸相似的多个用户

示例

private void finishFaceVerify() {
//params包含请求通用参数(authinfo,mchid等)
	WxPayFace.getInstance().finishFaceVerify(params,new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("returncode");
			String msg = (String) info.get("returnmsg");
			if (code == null || !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息,returnmsg:" + msg + " ").printStackTrace();
				return ;
			}
			UserInfo userInfo =(UserInfo)info.get("userinfo");
			if(userInfo == null || TextUtils.isEmpty(userInfo.getUserId()) {
			new RuntimeException("调用返回非成功信息,returnmsg: 用户信息为空").printStackTrace();
				return ;
			}
//到此处才算成功,一定要注意userinfo和userid判空
		});
	}
}
}
}

注意
开始识别返回用户信息后,不论是确认还是取消,都需要调用完成才能进行下一次识别
如果识别成功返回了单个用户信息,则不需要传递手机号,直接可以拿到当前的识别用户信息。
如果返回多个用户信息,需要商户传递手机号来获得对应的识别用户信息。

(14)获取支付凭证(getFacePayCredential)

public void getFacePayCredential(Map info,IWxPayfaceCallback cb);

请求参数
包含通用请求参数

请求参数 必填 类型 说明
user_id string 识别后的用户id
recog_mode int32 0:直接识别;1:手机辅助识别。
total_fee string 订单金额(数字),单位:分

返回参数(包含通用返回参数和通用errCode)
可能返回errcode 271378620 和 271378621,具体处理方式参考errcode说明。

返回参数 必填 类型 说明
face_token string 终端支付凭证
face_verify_id string 用户定位问题的唯一id

二级错误码参考

error_code return_msg 说明
271378533 请检查用户签约状态 用户状态异常
271378595 未找到用户信息,请联系客服 无对应用户信息
271378527 支付账号异常,请联系客服 被风控拦截
271378641 交易频繁,请等待重试 同人同金额5s内重复扣款

示例

private void getFacePayCredential() {
//params包含请求通用参数(authinfo,mch_id等)
	WxPayFace.getInstance().getFacePayCredential(params,new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("return_code");
			String msg = (String) info.get("return_msg");
			String faceToken= (String)info.get("face_token");
			if (code == null || !code.equals("SUCCESS") || TextUtils.isEmpty(faceToken)) {
				new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
				return ;
			}
//到此处才算成功,一定要注意faceToken判空
		}
	});
}
}

注意
开始识别返回用户信息后,不论是确认还是取消,都需要调用完成才能进行下一次识别。确认了会生成支付凭证,支付凭证生成需要一定时间。

(15)启动扫码(startCodeScanner)

public void startCodeScanner(Map info,IWxPayfaceCallback cb);

作用
微信人脸sdk启动摄像头进入扫码模式,扫描二维码。

注意
A、该方法注册的回调接口在stopCodeScanner之前,扫码成功都会回调;
B、该方法可以多次调用,但是扫码结果只会回调最后一次注册的回调;
C、扫码模式和刷脸互斥,一旦开始刷脸则SDK会退出扫码模式,扫码回调失效,如果需要扫码功能,需要刷脸结束后再次调用该方法启动扫码。

返回参数(包含通用返回参数和通用errCode)

特殊返回参数 必填 类型 说明
code_msg string 当扫码成功时返回扫码内容

示例

WxPayFace.getInstance().startCodeScanner(params,new IWxPayfaceCallback() {
	@Override
	public void response(Map info) throws RemoteException {
		if (info != null) {
			String return_code = (String) info.get("return_code");
			Integer errcode = (Integer) info.get("err_code");
			String return_msg = (String) info.get("return_msg");
			String code_msg = (String) info.get("code_msg");
			final String resultString = "startCodeScanner, return_code : " + return_code + " return_msg : " + return_msg + " code_msg: " + code_msg;
			/** 这里添加业务自定义的工作即可 注意该回调在异步线程 **/
		}
	}
});

(16)停止扫码(stopCodeScanner)

public void stopCodeScanner(Map info,IWxPayfaceCallback cb);

作用
微信人脸sdk停止摄像头扫码,退出扫码模式。

返回参数(包含通用返回参数和通用errCode)

示例

WxPayFace.getInstance().stopCodeScanner(params,,new IWxPayfaceCallback() {
	@Override
	public void response(Map info) throws RemoteException {
		if (info == null) {
			new RuntimeException("调用返回为空").printStackTrace();
			return;
		}
		String code = (String) info.get("return_code");
		String msg = (String) info.get("return_msg");
		if (code == null || !code.equals("SUCCESS")) {
			new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
			return ;
		}
	}
});

(17)跳转出厂检测(goToFactoryPage)

public void goToFactoryPage(Map info,IWxPayfaceCallback cb);

作用
微信人脸sdk进入出厂检测页面

注意

返回参数(包含通用返回参数和通用errCode)
无特殊参数,只有成功和系统错误两种

示例

WxPayFace.getInstance().goToFactoryPage(params,new IWxPayfaceCallback() {
	@Override
	public void response(Map info) throws RemoteException {
		if (info == null) {
			new RuntimeException("调用返回为空").printStackTrace();
			return;
		}
		String code = (String) info.get("return_code");
		String msg = (String) info.get("return_msg");
		if (code == null || !code.equals("SUCCESS")) {
			new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
			return ;
		}
	}
});

# 3.9 非必调接口

(1)清除人脸数据(clearFaceDatas)兜底逻辑接口

public void clearFaceDatas(Map info,IWxPayfaceCallback cb);

注意
A、只是用于逻辑兜底,保证特征同步异常情况下可以重新同步,不同机构会有不同的数据库,切换机构不建议调用此方法;
B、使用异常会导致机构不可用时间增长,建议紧急情况下使用;
C、清理本地人脸数据,清除不会立马拉取。

请求参数
包含通用请求参数

返回参数
如果returncode不为成功,则需要记录对应的errMsg,可以提示“清除人脸数据失败” 可能返回errcode 271378620 和 271378621,具体处理方式参考err_code说明。

示例

private void clearFaceDatas() {
//params包含请求通用参数(authinfo,mch_id等)
	WxPayFace.getInstance().clearFaceDatas(params,new IWxPayfaceCallback() {
		@Override
		public void response(Map info) throws RemoteException {
			if (info == null) {
				new RuntimeException("调用返回为空").printStackTrace();
				return;
			}
			String code = (String) info.get("return_code");
			String msg = (String) info.get("return_msg");
			if (code == null || !code.equals("SUCCESS")) {
				new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
				return ;
			}
		}
	});
}
}

(2)关闭摄像头常开(stopCamera)非常规接口

public void stopCamera(Map info,IWxPayfaceCallback cb);

注意
这里关闭摄像头建议在长时间无交易的时段来自行处理,关闭摄像头会有损识别效率,对于华捷的摄像头如果散热OK不建议做操作。

请求参数
包含通用请求参数

返回参数(包含通用返回参数和通用errCode)
可能返回errcode 271378620 和 271378621,具体处理方式参考errcode说明。

示例

private void stopCamera() {
//params包含请求通用参数(authinfo,mch_id等) WxPayFace.getInstance().stopCamera(params,new IWxPayfaceCallback() {
	@Override
	public void response(Map info) throws RemoteException {
		if (info == null) {
			new RuntimeException("调用返回为空").printStackTrace();
			return;
		}
		String code = (String) info.get("return_code");
		String msg = (String) info.get("return_msg");
		if (code == null || !code.equals("SUCCESS")) {
			new RuntimeException("调用返回非成功信息,return_msg:" + msg + " ").printStackTrace();
			return ;
		}
	}
});
}
}

(3)AAR日志自定义(setLog) 非常规接口

public void setLog(WxLog log);

请求参数
传入WxLog的实现

返回参数

示例

private void setLog() {
	WxLog logImpl = new WxLog() {
		@Override
		public void d(String tag, String msg) {
//可使用服务商自己的日志输出
		}
		@Override
		public void i(String tag, String msg) {
//可使用服务商自己的日志输出
		}
		@Override
		public void e(String tag, String msg) {
//可使用服务商自己的日志输出
		}
		@Override
		public void e(String tag, String msg, Throwable e) {
//可使用服务商自己的日志输出
		}
	};
	WxPayFace.getInstance().setLog(logImpl);
}

# 3.10 终端标准流程

(1)设备运行机制

定期重启机制一定要有,避免因ROM或者商户APP或者支付SDK运行太长时间导致突发异常,建议凌晨非高峰期可以自行重启一次(推荐时间凌晨1:00-3:00,将凌晨1:00前作为升级时间)。

(2)获取支付凭证去后台扣款流程
A、建议UI上明确区分在线模式和断网模式,只有极端网络情况才运行断网模式,常规网络都要走在线模式;
B、在线模式是在用户点击确认后,必须后台扣款成功才能展示成功结果,坏账率低,无需和支付侧对接扣款失败和垫资问题;
C、断网模式是在用户点击确认后,后台可以延后扣款,终端拿到支付凭证并且商户确认可以扣款就能展示成功结果,因为未经过后端风控,可能导致坏账、扣款失败和垫资问题;
D、获取用户信息后,获取支付凭证和用户点击确认流程可以并行,从而优化支付耗时。

(3)预览绑定流程
A、绑定surfaceview推荐全局使用同一个示例;
B、绑定最佳时机为surfaceview不会再发生大小改变或者隐藏的时刻,避免需要动态适配;
C、可以手动removeSurfaceview,重新绑定也会自动进行remove。

(4)识别&支付流程
默认流程成功:

默认流程

取消订单(用户希望取消/结束流程):

结束流程

页面跳转可能的异化流程
开始识别->停止识别->完成识别->获取支付凭证->开始识别->完成识别->停止识别->获取支付凭证

关闭摄像头渲染和识别时机
A、停止识别;
B、完成识别;
C、获取支付凭证;
D、开始识别(会停掉前一次识别)。

清除上一次识别数据时机
A、完成识别(仅限失败);
B、获取支付凭证(不论成功失败)。

“停止识别”和“清除当前识别数据”

停止识别作用只是停止摄像头渲染和识别,并不会清除掉上次的数据,可以在任何阶段调用,标准的结束必须以获取支付凭证为结尾。

A、调用“开始识别”会自动清除当前识别数据,并停止识别再启动识别,如果成功会直接停止识别;
B、调用“停止识别”只停止当前识别,不清除当前识别数据;
C、调用“完成识别”失败会清理上次识别数据,成功不做处理;
D、调用“获取凭证”不论成功失败都会直接停止当前识别并清理识别数据。

# 3.11 常见问题

(1)刷脸SDK仅用于识别,支付环节默认走非微信支付渠道
需要保证获取支付凭证接口被调用,保证真实金额传入获取支付凭证,可以用金额0去后台对当前支付凭证的安全性进行验证,保证支付流程完善。

(2)初始化提示“初始化失败”
A、检查对应的release调用时机,不要太频繁的release,每次release后初始化耗时较长;
B、调用其它API都依赖初始化成功后再操作,如果初始化未完成就调用任意非初始化API,就会提示该问题,碰上这两类错误码,只需要重试初始化即可。

(3)K12UserInfo和UserInfo的keep问题
AAR对返回的json字符串做了类型封装,本质上新旧AAR对apk的调用都没有异常,这里商户app升级后使用新版aar需要简单调整下对应的userinfo类型,并且在proguard里 -keep class com.tencent.wxpayface.data.UserInfo{ *; };

(4)parcelable exception 空指针
注意对err_code判空,不能直接转换为int,而应该使用Integer,否则会导致支付SDK无响应。

(5)摄像头温度过热问题
优先保证摄像头常开,保证体验;如果散热问题特别严重,可以尝试连续一段时间比如10分钟内没有识别,调用stopCamera,下一次启动识别耗时会变长,但是可以缓解散热问题。

(6)认证失败问题
认证失败可能出现在任意请求之内,如果出现新获取的authinfo无法调用,请检查机器时间,原则上机器时间应与网络时间同步。

(7)第一次调用摄像头或者其它api耗时超长
获取authinfo启动app后,第一次识别需要加载识别相关资源,可以提前调用preloadSdkEnv来提前预启动,保证第一次识别速度很快。

(8)商户识别流程设计
尽可能保证时序串行,避免出现重复扣款情况。
注意:商户可以按需求设计,比如不允许同人同金额10s内支付等逻辑。

(9)现场用户需要弯腰踮脚
建议将预览画面按照长宽比3:4来实现,方便用户最大范围进行识别,避免出现用户脸不在预览画面中心,误以为不能识别,其实可以识别的情况。

(10)数据库初始化失败271378588错误
A、部分设备可能重启或者运行时间久后,设备读写速度变慢,建议开机重启后延迟一段时间,比如5s再进行init,避免时序紊乱;
B、不要频繁地调用release,release后需要重新环境初始化,导致耗时增加,可能出现该错误。

(11)双胞胎算法不能区分问题
A、双胞胎不需要区分
绑定相同⼿机号、微信号,系统会默认合并到和现场照更相似的用户身份进⾏扣款。

B、双胞胎需要区分
绑定不同⼿机号、微信号,系统会提示需要输入手机号验证,从⽽区分当前身份。

# 4. 后台接口

更新记录
版本 简要说明 修改日期
1.0 1. 查询结构支持机构名查询
2. 调整扣款接口,改为同步模式
3. 调整获取SDK鉴权信息方式
2019/8/5
1.1 查询用户信息增加签约状态返回 2019/8/8
1.2 增加流程图 2019/8/11
1.3 1. 增加敏感字段列表
2. GetUser接口调整字段名称
3. class修改为class_name
4. 其它
2019/8/28
1.4 增加联调环境说明 2019/8/28
1.5 更正url 2019/8/28
1.6 所有参数中的mch_code改成mchid 2019/8/31
1.7 扣款接口增加business_info参数 2019/9/4
1.8 增加商户主动解约接口。解约后,刷脸用户将无法支付,除非重新签约 2020/1/19
1.9 增加测试环境配置方法 2020/4/2
2.0 增加企业食堂和K12调用说明 2020/4/10
2.1 增加支持分账的扣款接口 2020/8/14
2.2 用户查询接口、预签约接口修改,增加按照签约ID查询签约信息接口 2020/9/28
2.3 增加还款小程序跳转协议 2020/11/5
2.4 扣款接口新增是否为垫资,新增查单接口 2020/11/13
2.5 接口5扣款接口标记为删除 2020/11/25
2.6 将机构管理相关接口列为待下线状态,建议服务商通过商户平台管理机构 2021/3/22
2.7 扣款接口新增error_type 2021/4/21
2.8 上线新版authinfo接口 2021/5/20
2.9 上线获取还款链接接口 2021/6/22
3.0 下掉旧扣款接口 2021/8/31

名词定义
● 商户后台系统:商户侧后台处理系统。
● 商户刷脸APP:商户侧的刷脸支付APP。
● 商户小程序:商户提供给用户的小程序。
● 微信刷脸后台系统:微信侧刷脸后台处理系统。
● 微信离线刷脸SDK:微信侧提供的刷脸识别SDK。
● 微信刷脸小程序:微信侧提供的小程序,用户刷脸用户开通、签约等操作。
● 刷脸用户:刷脸消费用户。如学生、教职工。
● 支付用户:实际支付的用户,如家长、教职工。
● 收银员:负责收款的人或机器。
● 机构:学校、公司等都是机构,当前以机构为单位维护人脸特征库。
● out_user_id:刷脸用户标识,需要商户保证同一个刷脸用户在一个机构下唯一,不要给同一个用户创建多个out_user_id,否则可能导致用户无法识别,目前限制同一个微信号不允许绑定同一个机构下多个同名用户。
● user_id:刷脸用户标识,微信侧生成。
● organization_id:机构唯一标识,一个机构下的所有用户的人脸特征组成了该机构对应的人脸特征库。
● face_feature_version:人脸特征版本。由于算法升级,不同版本的识别算法提取的人脸特征会有差异。

业务流程
微信离线人脸APP调用凭证获取

APP调用凭证

参考获取authinfo接口。

商户录入刷脸用户流程
目前录入刷脸用户有如下入口,分别为:
(1)商家统一采集学生信息,家长签约时则无需录入照片。
用户流程1

(2)家长签约时录入照片。
用户流程2

(3)重新采集时更换学生照片。
用户流程3

扣款流程
扣款流程为同步接口,获取扣款相关参数请参考微信离线人脸APP接入文档。

错误码和错误提示
当请求处理失败时,除了HTTP状态码表示错误之外,API将在消息体返回错误相应说明具体的错误原因。

错误字段列表为:

字段名 变量名 类型 必填 示例 描述
错误码 code string(32) PARAM_ERROR /
错误描述 message string(512) 参数错误 /

code列表:

状态码 描述
SIGN_ERROR 签名错误
INVALID_REQUEST 无效请求

签名
所有接口调用均需要签名,请点击签名方法进行查阅。

字段有效性规定

字段名 含义 约束 示例
out_user_id 商户侧生成,刷脸用户唯一标识 1. 商户ID下全局唯一;
2. 只能包含字母、数字;
3. 长度不超过50字节。
FEX868felix3
user_id 微信侧生成,刷脸用户唯一标识 1. 商户ID下全局唯一;
2. 必须为字母数字的组合;
3. 长度不超过50字节。
FEX868felix3
organization_name 机构名称,商户定义 1. 合法的UTF8字符串;
2. 长度不超过60字节。
深圳市宝安区铁岭第一高级中学
organization_id 微信侧生成,机构唯一标识 1. 必须为字母数字的组合;
2. 长度不超过50字节。
LIJX868felix3
user_name 用户姓名 1. 合法的UTF8字符串;
2. 长度不超过50字节。
张三四
李王五
class_name 班级名 1. 合法的UTF8字符串;
2. 长度不超过50字节。
高三五班
occupation 职业 1. 合法的UTF8字符串;
2. 长度不超过50字节。
工程师
教师

敏感字段列表

根据微信APIv3的要求,所有敏感信息经网络传输需要进行二次加密,加密方法请参考《敏感信息加解密》

敏感字段列表如下

字段名 含义
user_name 用户姓名

下面将不再单独对每个字段进行说明。

测试环境联调方法
注意测试环境不保证服务可用性,因此仅在特殊情况下使用与微信侧进行联调,其他非必要场景请不要使用测试环境,使用前请与微信侧确认测试环境可用,配置方法如下,任选其一即可,不可同时配置:
方法一:HTTP代理模式,139.199.171.252:8089
方法二:HOST模式,183.3.224.148 api.mch.weixin.qq.com

接口列表

# 4.1 查询机构信息接口

机构申请请点击参考《学校机构ID申请说明》

接口定义
根据organization_id查询机构信息:
GET https://api.mch.weixin.qq.com/v3/offlinefacemch/organizations?organization_id=xxx

根据organization_name查询机构信息:
GET https://api.mch.weixin.qq.com/v3/offlinefacemch/organizations?organization_name=url_encode(name)

请求参数

返回结果

状态码 描述
200 成功
其他 失败

状态为200时:

字段名 变量名 类型 必填 示例 描述
机构ID organization_id string(50) DBES323aeb 机构唯一ID,由数字、字母组成
机构名称 organization_name string(50) 南山中兴小学部 机构名称

# 4.2 获取授权凭证接口

授权凭证用与拉起小程序、H5等。
token有效期为5分钟,在商户小程序跳转签约小程序时获取,不要提前获取。
集中采集时建议使用该接口。
用户签约时建议使用预签约接口。

接口定义
POST https://api.mch.weixin.qq.com/v3/offlinefacemch/tokens

请求参数

字段名 变量名 类型 必填 示例 描述
使用场景 scene string(32) WEBSESSION 颁发的授权凭证将要使用的场景;
WEBSESSION:小程序调用凭证。
小程序/h5鉴权场景初始化数据 web_init_data object / 小程序/h5鉴权场景初始化数据;
scene等于WEBSESSION时必填。

web_init_data:

字段名 变量名 类型 必填 示例 描述
商户刷脸用户ID out_user_id string(50) 123456 商户侧刷脸用户ID,只能包含字母、数字。同一个商户下,该值必须唯一。
机构ID organization_id string(50) DBES323aeb 机构唯一ID,由数字、字母组成。

返回结果

状态码 描述
200 成功
其它 失败

状态码为200时,结果参数为:

字段名 变量名 类型 必填 示例 描述
授权凭证 token string(50) TKeinf3345ABC 由字母数字组成。

# 4.3 刷脸用户信息查询接口

接口定义
GET https://api.mch.weixin.qq.com/v3/offlinefacemch/organizations/{organization_id}/users/out-user-id/{out_user_id}

请求参数

返回结果

状态码 描述
200 成功
其它 失败

状态码为200时,返回如下字段:

字段名 变量名 类型 必填 示例 描述
刷脸用户ID user_id string(50) 34fdeEFGFE 微信侧刷脸用户唯一ID
商户刷脸用户ID out_user_id string(50) 123456 商户侧刷脸用户ID,只能包含字母、数字。同一个商户下,该值必须唯一
机构ID organization_id string(50) DBES323aeb 机构唯一ID,由数字、字母组成
姓名 user_name string(32) 张三 姓名
用户类型 user_type string(16) STUDENT 学生:STUDENT
职工:STAFF
学生信息 student_info object 详细见下文 user_type为STUDENT时必填,字段见下文
职工信息 staff_info object 详细见下文 user_type为STAFF时必填,字段见下文
用户状态 status string(16) NORMAL 1. NOMAL:正常状态
2. DISABLED:禁用状态,此时支付被限制
签约状态 contract_state string CONTRACTED NOT_CONTRACTED:未签约
TERMINATED:已解约
CONTRACTED:已签约
人脸图片上传状态 face_image_ok bool true
false
用户采集的照片
签约ID contract_id string / 用户已签约/已解约时存在

student_info:

字段名 变量名 类型 必填 示例 描述
班级名 class_name string(64) 三年级二班 班级名

staff_info:

字段名 变量名 类型 必填 示例 描述
职业 occupation string(64) 教职工 用户职业信息

# 4.4 刷脸用户信息修改接口

接口定义

PATCH https://api.mch.weixin.qq.com/v3/offlinefacemch/organizations/{organization_id}/users/out-user-id/{out_user_id}

请求参数

字段名 变量名 类型 必填 示例 描述
姓名 user_name string(32) 张三 姓名,加密上传
用户类型 user_type string(16) STUDENT 学生:STUDENT
职工:STAFF
注意:企业食堂该值固定为STAFF。
学生信息 student_info object 详情见下文 user_type为STUDENT时必填,字段见下文。
职工信息 staff_info object 详情见下文 user_type为STAFF时必填,字段见下文。
状态 status string NORMAL 1、"NORMAL":正常状态;
2、"DISABLED":禁用,后续刷脸用户将无法消费。
手机号 phone string 136xxxxxxxx 手机号,加密上传

返回结果

状态码 描述
204 成功
其它 失败

# 4.5 获取authinfo接口

注意建议authinfo每1小时内获取一次。

接口定义
POST https://api.mch.weixin.qq.com/v3/offlineface/authinfo

请求参数

字段名 变量名 类型 必填 示例 说明
服务商appid sp_appid string 示例值: wx369ab4160391b078;
字符长度限制: [1, 32]
商户appid
子appid sub_appid string 有则必传 示例值: wx369ab4160391b078;
字符长度限制: [0, 32]
子商户APPID
子商户号 sub_mchid string 示例值: 1900000109;
字符长度限制: [0, 32]
子商户号
设备id device_id string 示例值: TXAP12029003744ND002112;
字符长度限制: [1, 32]
终端设备唯一ID,必须为数字、字母、下划线的组合
原始数据 raw_data string 示例值: kh5HJYlzqXosbqJCOYXASBxYozukRFjg5P9MY;
字符长度限制: [1, 2048]
初始化数据,由微信人脸SDK的接口返回
机构id organization_id string 示例值: OCAABBDDee;
字符长度限制: [1, 64]
机构ID,注意创建机构的商户号和mch_id应该保持一致

返回结果

状态码 错误码 错误说明
200 请求正确处理 获取authinfo成功
500 SYSTEM_ERROR 请稍后重试
400 PARAM_ERROR 参数错误,请检查参数
400 INVALID_REQUEST 表示请求参数符合格式,但不符合业务规则
429 RATELIMIT_EXCEEDED 请求达到速率限制
字段名 变量名 类型 必填 示例 描述
授权信息 authinfo string 示例值: kh5HJYlzqXosbqJCOYXASBxYozukRFjg5P9MY;
字符长度限制: [1, 4096]
SDK调用凭证,用于调用SDK的人脸识别接口

# 4.6 解除刷脸用户签约关系接口

接口定义

POST https://api.mch.weixin.qq.com/v3/offlinefacemch/organizations/{organization_id}/users/user-id/{user_id}/terminate-contract

请求参数

返回结果

状态码 描述
204 成功
其它 失败

# 4.7 预签约接口

接口定义
POST https://api.mch.weixin.qq.com/v3/offlineface/contracts/presign

用户能够扣款的前提是已经完成签约操作,签约流程如下:
A、用户在商户小程序发起签约;
B、商户调用该接口进行预签约,该接口会返回presign_token;
C、商户小程序携带presign_token跳转到微信侧人脸小程序,用户在微信侧人脸小程序完成签约操作。
注意
a、一键绑卡不是支持所有银行卡,上线前请先测试是否支持该银行卡
b、建议上线前一周完成调试
c、签约完成务必多次扣款,防止由于银行限制每日扣款次数、扣款金额等影响用户消费
d、指定卡签约建议异步扣款,否则银行维护会导致不能扣费,影响学生吃饭
e、presign_token有效期为5分钟,在商户小程序跳转签约小程序时获取,不要提前获取

请求参数

字段名 变量名 类型 必填 示例 描述
业务类型 business_name string K12 K12、GROUP_DINING
刷脸用户信息 facepay_user object 张三 刷脸用户信息
签约指定银行卡 limit_bank_card object xxxxx 签约绑定指定卡
签约模式 contract_mode string LIMIT_BANK_CARD LIMIT_BANK_CARD:指定卡签约;
PRIORITY_BANK_CARD:优先卡签约;
LIMIT_NONE:任意卡签约

facepay_user:

字段名 变量名 类型 必填 示例 描述
商户用户ID out_user_id string 123456 商户侧对用户唯一标识
刷脸用户名 identification_name string 张三 按照APIV3规范加密
机构ID organization_id string DBES323aeb 机构id
证件信息 identification object IDCARD identification_type支持IDCARD、EEP_HK_MACAU、PASSPORT_NO
手机号码 phone string xxxxxx 按照APIV3规范加密

limit_bank_card:

字段名 变量名 类型 必填 示例 描述
银行卡号 bank_card_number string xxxxx 按照APIV3规范加密
开卡人姓名 identification_name string 张三 按照APIV3规范加密
开卡人证件 identification object xxxxx identification_type固定值:IDCARD
银行卡有效期 valid_thru string 08/21 格式mm/yy,仅部分银行需要
银行类型 bank_type string 工商银行 强烈建议填写,采用字符串类型的银行标识,值列表详见银行类型
开卡预留手机号 phone string xxxxx 建议填写,按照APIV3规范加密

identification:

字段名 变量名 类型 必填 示例 描述
证件类型 identification_type string IDCARD 固定值:IDCARD
证件ID identification_number string xxxxx 数字字母组成,按照APIV3规范加密

返回结果

字段名 变量名 类型 必填 示例 描述
会话id presign_token string(64) xxxxx 跳转小程序携带

# 4.8 申请扣款接口

接口定义
POST https://api.mch.weixin.qq.com/v3/offlineface/transactions

请求参数

字段名 变量名 类型 必填 示例 描述
支付凭证 auth_code string 示例值: fewjfwoe3323wwxxxxxxxxx 由刷脸SDK返回,作为唯一扣款凭证
服务商公众号appid sp_appid string 示例值: wx333333333333333
字符字节限制: [0, 32]
服务商公众号appid
服务商商户号 sp_mchid string 示例值: 198798777
字符字节限制: [0, 32]
服务商商户号
子商户公众号appid sub_appid string 示例值: wx3333333333
字符字节限制: [0, 32]
子商户公众号appid
子商户商户号 sub_mchid string 示例值: 3233122121
字符字节限制: [0, 32]
子商户号
金额信息 amount object 示例值: 3 金额,单位:分
支付场景信息 scene_info object 详情见下表 详情见下表
优惠标记 goods_tag string 示例值: xtedx 优惠标记
商品信息 description string 示例值: XX小学午餐, XX中学惠客隆超市
字符字节限制: [0, 128]
商品信息,长度不大于128
商品附加信息 attach string 示例值: id=xxx
字符字节限制: [0, 128]
商品附加描述,长度不大于128
结算信息 settle_info object 示例值: false 详情见下表
商户订单号 out_trade_no string 示例值: IDXfewfe3
字符字节限制: [0, 32]
长度不大于32
业务信息 business object 详情见下表 详情见下表

amount定义如下:

字段名 变量名 类型 必填 示例 描述
总金额 total int64 示例值: 100
值限制: 1 ≤ value ≤ 1000000000
字符字节限制: [1, 10]
订单总金额,单位分,只能为整数
货币类型 currency string(16) 示例值: CNY
字符字节限制: [0, 16]
符合ISO 4217标准的三位字母代码,目前仅支持人民币:CNY

scene_info定义如下:

字段名 变量名 类型 必填 示例 描述
设备IP device_ip string 示例值: 8.8.8.8
字符字节限制: [0, 45]
设备IP

business定义如下:

字段名 变量名 类型 必填 示例 描述
平台产品ID business_product_id int 示例值: 2 2:K12项目
11:企业团餐
平台场景ID business_scene_id int 示例值: 3 K12可选:
● 3 食堂
● 4 超市
● 5 校医院
● 6 K12测试场景
企业团餐可选:
● 124 团餐测试
● 125 企业食堂
● 126 腾讯食堂

settle_info定义如下:

字段名 变量名 类型 必填 示例 描述
是否支持分账 profit_sharing bool 示例值: false 分账使用

返回结果

状态码 描述
200 处理成功
其它 失败

状态码为200时:

字段名 变量名 类型 必填 示例 描述
服务商公众号appid sp_appid string 示例值: wx333333333333333
字符字节限制: [0, 32]
服务商公众号appid
服务商商户号 sp_mchid string 示例值: 198798777
字符字节限制: [0, 32]
服务商商户号
子商户公众号appid sub_appid string 示例值: wx3333333333
字符字节限制: [0, 32]
子商户公众号appid
子商户商户号 sub_mchid string 示例值: 3233122121
字符字节限制: [0, 32]
子商户号
支付用户信息 payer object 详情见下表 详情见下表
金额信息 amount object 详情见下表 详情见下表
优惠信息 promotion_detail array 暂无 暂不支持,可不关注
支付场景信息 scene_info object 暂无 与请求信息定义相同
付款银行 bank_type string 示例值: 招商银行
字符字节限制: [0, 16]
用户扣款银行信息
交易类型 trade_type string 示例值: NATIVE, JSAPI, APP, MWEB
字符字节限制: [0, 16]
支付成功才返回
"AUTH" - 行业代扣
交易状态 trade_state string 示例值: SUCCESS
字符字节限制: [0, 32]
支付成功才返回
“SUCCESS” - 支付成功(支付成功无需处理)
“REFUND" - 转入退款(支付成功无需处理)
“NOTPAY” - 未支付(重试扣款)
“CLOSED" - 已关闭(换单号重试)
“REVOKED” - 已撤销(换单号重试)
“USERPAYING” - 用户支付中(重试扣款)
“PAYERROR” - 支付失败(换单号重试)
交易描述 trade_state_description string 示例值: 支付失败,请重新下单支付
字符字节限制: [0, 256]
订单交易状态
欠款状态 debt_state string 示例值: DEBT NOT_DEBT:无欠款(无垫资)
DEBT:有欠款(垫资支付)
REPAYMENT:(已还款)
商品信息 description string 示例值: 初级中学午餐
字符字节限制: [0, 128]
商品信息
商户附加信息 attach string 示例值: id=1
字符字节限制: [0, 128]
商品附加描述,长度不大于128
支付成功时间 success_time string 示例值: 2015-05-20T13:29:35.120+08:00
字符字节限制: [0, 32]
使用ISO 8601所定义的格式:
微信订单号 transaction_id string 示例值: 4200032343298099898
字符字节限制: [0, 32]
支付成功才返回
还款微信订单号 repayment_transaction_id string 示例值: 1217752501201407033233368018
字符字节限制: [0, 32]
订单为垫资支付且用户已还款时产生的微信交易订单号,当欠款单状态为REPAYMENT时返回
商户订单号 out_trade_no string 示例值: 1217752501201407033233368018
字符字节限制: [0, 32]
商户订单号
错误分类 error_type string / trade_state为PAYERROR时存在,“NOT_ENOUGH”和“NOTENOUGH”表示用户余额不足

payer定义如下:

字段名 变量名 类型 必填 示例 描述
公众下的openid sp_openid string 示例值: fefewfwe
字符字节限制: [0, 128]
付款用户信息
子公众下的openid sub_openid string 示例值: fefewfwe
字符字节限制: [0, 128]
付款用户信息

amount定义如下:

字段名 变量名 类型 必填 示例 描述
订单金额 total int64 示例值: 3 金额,单位:分
用户支付金额 pay_total int64 示例值: 3 金额,单位:分
货币类型 currency string 示例值: CNY 货币类型,目前只支持人民币
用户支付货币类型 pay_currency string 示例值: CNY 货币类型,目前只支持人民币

返回码处理建议:

httpcode 错误码 处理方式
200 请求正确处理,应该判断订单状态 “SUCCESS” - 支付成功(支付成功无需处理)
“REFUND”-转入退款(支付成功无需处理)
“NOTPAY”-未支付(24小时内参数不变重试扣款)
“CLOSED”-已关闭(参数不变换单号重试)
“REVOKED”-已撤销(参数不变换单号重试)
“USERPAYING”-用户支付中(24小时内参数不变重试扣款)
“PAYERROR”-支付失败(换单号重试)
500 SYSTEM_ERROR 请稍后重试,建议同一笔订单每天重试不要超过5次,频繁重试会导致该用户无法扣款
400 PARAM_ERROR 参数错误,请检查参数
400 INVALID_REQUEST 目前子商户未开通权限、凭证已经使用过并且扣款成功、请求参数和凭证信息不一致、凭证正在扣款又换单号重试、重入请求变更了参数都会返回该错误码,表示请求参数符合格式,但不符合业务规则,需要服务商定位问题并修正代码
429 RATELIMIT_EXCEEDED 请求达到速率限制

# 4.9 签约查询接口

根据签约id查询签约信息。
接口定义
GET https://api.mch.weixin.qq.com/v3/offlineface/contracts/{contract_id}?appid=XXXX

请求参数

字段名 变量名 类型 必填 示例 描述
签约id contract_id string 示例值: CI8CD208Z7e9906f89 签约回调通知、用户查询接口返回签约ID
appid appid string 示例值: wx8888888888 必须和商户号有绑定关系,建议扣款接口、商户签约小程序和该字段保持一致

返回结果

状态码 描述
200 成功
其它 失败

状态码为200时,结果参数为:

字段名 变量名 类型 必填 示例 描述
签约ID contract_id string 示例值: wx88888888
字符字节限制: [0, 64]
用户签约ID
商户号 mchid string 示例值: 2480278041
字符字节限制: [0, 32]
允许扣款商户号
机构id organization_id string 示例值: OAABBCCDDeeff
字符字节限制: [0, 64]
机构唯一ID,由数字、字母组成
用户id user_id string 示例值: FU40F305Z4e2bb7d
字符字节限制: [0, 64]
刷脸用户ID
签约用户openid openid string 示例值: AFDSJfhdf8744
字符字节限制: [0, 128]
传入appid时返回,扣款微信号对应openid
签约状态 contract_state string 示例值: CONTRACTED
字符字节限制: [0, 32]
已签约:CONTRACTED
未签约:NOT_CONTRACTED
已解约:TERMINATED
签约时间 contract_signed_time string 示例值: 2018-06-08T10:34:56+08:00
字符字节限制: [0, 32]
签约时间
解约时间 contract_terminated_time string 示例值: 2018-06-08T10:34:56+08:00
字符字节限制: [0, 32]
解约时间,已解约时返回
签约模式 contract_mode string 示例值: PRIORITY_BANK_CARD
字符字节限制: [0, 32]
LIMIT_BANK_CARD:指定卡签约;
PRIORITY_BANK_CARD:优先卡签约;
LIMIT_NONE:任意卡签约
签约卡来源 contract_bank_card_from string 示例值: MERCHANT_LIMITED_BANK_CARD
字符字节限制: [0, 64]
MERCHANT_LIMITED_BANK_CARD:商户指定的签约卡;
USER_SELECT_FREE:用户选择的签约卡。

# 4.10 签约状态变更回调通知(签约、解约都会回调)

能力背景

服务商为学校开发基于师生的用户管理体系时,需要维护用户的采集和签约状态,并同步至刷脸设备。目前,服务商只能获取用户签约信息,不能获取用户解约信息,导致服务商无法维护用户状态,影响用户正常使用。

能力简介

刷脸用户在完成签约或解约后,微信会通知商户用户签约状态变更。商户需要接收处理,并返回应答。

具体开发内容请点击《离线刷脸签约状态变更回调》进行查阅。

接入流程

详情接入请见《申请用户解约通知申请表》

接入周期
每周五12:00截止本周配置信息收集,并在下个工作日上午12:00前配置完成。

# 4.11 还款小程序跳转协议

appid:wxa834b152dd018e25
path:pages/index/index?business_product_id=XXXX(2表示K12,11表示企业团餐)

# 4.12 查询重采请求接口

离线刷脸业务中,偶尔会出现前期采集头像质量不高,导致算法升级后,旧的头像无法生成有效的人脸特征,影响用户使用刷脸服务。因此,需要对用户的头像进行重采。

接口定义
GET https://api.mch.weixin.qq.com/v3/offlineface/face-collections/{collection_id}。

请求参数

字段名 变量名 类型 必填 示例 描述
重采ID collection_id string 示例值: FC2353ZJIHOJKHOIIOI;
字符字节限制: [0, 64]
微信侧为人脸重采生成的唯一请求ID
重采ID可以通过查询重采用户列表接口获取到。

返回结果

状态码 描述
200 成功
404 重采ID不存在, 说明不需要重采

状态码为200时,结果参数为:

字段名 变量名 类型 必填 示例 描述
重采ID collection_id string 示例值: FC2353ZJIHOJKHOIIOIJ
字符字节限制: [0, 64]
微信侧为人脸重采生成的唯一请求ID
刷脸用户ID user_id string 示例值: FUxxxxxxxxxx
字符字节限制: [0, 64]
刷脸用户ID
机构ID organization_id string 示例值: Oxxxxfefwefwfewfwe
字符字节限制: [0, 64]
机构唯一ID,由数字、字母组成
重采状态 collection_state string 示例值: COLLECTION_REQUIRED
字符字节限制: [0, 64]
合法的重采状态有:COLLECTION_REQUIRED: 该刷脸用户需要进行重采;
PHOTO_UPLOADED: 照片已上传;
COMPLETE: 支付用户已经确认照片, 重采结束。
注册照上传时间 register_photo_upload_time string 示例值: 2018-05-23T12:13:50+08:00
字符字节限制: [0, 64]
商户通过集中采集功能或者用户自行采集人脸照片后,照片上传成功的时间。
支付用户确认时间 confirm_time string 示例值: 2018-05-23T12:13:50+08:00
字符字节限制: [0, 64]
支付用户确认注册照的时间, 用户确认之后, 该注册照将作为人脸识别的底照;
当用户确认注册照后, 重采就全部完成了。

# 4.13 查询重采用户列表接口

通过该接口,商户可以获取需要重采的用户列表。 根据该列表,可以安排进入学校进行集中采集或者通知家长配合采集。
采集完成后,通过小程序的重采确认接口,让用户确认重采的人脸照片。
建议商户在收到重采通知后,或者是定时轮询(轮询周期不用太高, 填级别即可),通过该接口获取重采列表, 安排后续工作。

接口定义
GET https://api.mch.weixin.qq.com/v3/offlineface/face-collections?organization_id={organization_id}。

请求参数

字段名 变量名 类型 必填 示例 描述
机构ID organization_id string 示例值: Ofewewfwefweewf
字符字节限制: [0, 64]
机构ID
列表偏移 offset uint64 示例值: 30 非0整数,该次请求资源的起始位置,从0开始计数。调用方选填,默认为0。
offset需要根据结果集的个数动态调整,当结果集为0时,表明已经拉取完毕了。
资源个数 limit uint64 示例值: 20 非0非负的整数,该次请求可返回的最大资源条数。调用方选填,默认值建议为20。

返回结果

状态码 描述
200 成功

状态码为200时,结果参数为:

字段名 变量名 类型 必填 示例 描述
重采列表 face_collections 数组 详情见下表 重采列表为空时, 表明没有更多资源了; 详情见下表。

重采列表单个对象结构:

字段名 变量名 类型 必填 示例 描述
重采ID collection_id string 示例值: FC2353ZJIHOJKHOIIOIJ
字符字节限制: [0, 64]
微信侧为人脸重采生成的唯一请求ID
刷脸用户ID user_id string 示例值: FUxxxxxxxxxx
字符字节限制: [0, 64]
刷脸用户ID
机构ID organization_id string 示例值: Oxxxxfefwefwfewfwe
字符字节限制: [0, 64]
机构ID
重采状态 collection_state string 示例值: COLLECTION_REQUIRED
字符字节限制: [0, 64]
合法的重采状态有:COLLECTION_REQUIRED: 该刷脸用户需要进行重采;
PHOTO_UPLOADED: 照片已上传;
COMPLETE: 支付用户已经确认照片, 重采结束。
注册照上传时间 register_photo_upload_time string 示例值: 2018-05-23T12:13:50+08:00
字符字节限制: [0, 64]
商户通过集中采集功能或者用户自行采集人脸照片后,照片上传成功的时间。
支付用户确认时间 confirm_time string 示例值: 2018-05-23T12:13:50+08:00
字符字节限制: [0, 64]
支付用户确认注册照的时间, 用户确认之后, 该注册照将作为人脸识别的底照;
当用户确认注册照后, 重采就全部完成了。

# 4.14 查单接口

接口定义
GET https://api.mch.weixin.qq.com/v3/offlineface/transactions/out-trade-no/{out_trade_no}?sp_mchid={sp_mchid}&sub_mchid={sub_mchid}&business_product_id={business_product_id}

请求参数

字段名 变量名 类型 必填 示例 描述
商户订单号 out_trade_no string 示例值: 1217752501201407033233368018
字符字节限制: [0, 32]
商户订单号
服务商商户号 sp_mchid string 示例值: 198798777
字符字节限制: [0, 32]
服务商商户号
子商户商户号 sup_mchid string 示例值: 3233122121
字符字节限制: [0, 32]
子商户号
平台产品ID business_product_id int 示例值: 2 2:K12项目
11:企业团餐
状态码 描述
200 成功
其他 失败

状态码为200时:body和申请扣款接口一致。

字段名 变量名 类型 必填 示例 描述
服务商公众号appid sp_appid string 示例值: wx333333333333333
字符字节限制: [0, 32]
服务商公众号appid
服务商商户号 sp_mchid string 示例值: 198798777
字符字节限制: [0, 32]
服务商商户号
子商户公众号appid sub_appid string 示例值: wx3333333333
字符字节限制: [0, 32]
子商户公众号appid
子商户商户号 sub_mchid string 示例值: 3233122121
字符字节限制: [0, 32]
子商户号
支付用户信息 payer object 详情见下表 详情见下表
金额信息 amount object 详情见下表 详情见下表
优惠信息 promotion_detail array 暂无 暂不支持,可不关注
支付场景信息 scene_info object 暂无 与请求信息定义相同
付款银行 bank_type string 示例值: 招商银行
字符字节限制: [0, 16]
用户扣款银行信息
交易类型 trade_type string 示例值: NATIVE, JSAPI, APP, MWEB
字符字节限制: [0, 16]
支付成功才返回
"AUTH" - 行业代扣
交易状态 trade_state string 示例值: SUCCESS
字符字节限制: [0, 32]
支付成功才返回
“SUCCESS”-支付成功(支付成功无需处理);
“REFUND”-转入退款(支付成功无需处理);
“NOTPAY”-未支付(重试扣款);
“CLOSED”-已关闭(换单号重试);
“REVOKED”-已撤销(换单号重试);
“USERPAYING”-用户支付中(重试扣款);
“PAYERROR”-支付失败(换单号重试)。
交易描述 trade_state_description string 示例值: 支付失败,请重新下单支付
字符字节限制: [0, 256]
订单交易状态
欠款状态 debt_state string 示例值: DEBT NOT_DEBT:无欠款(无垫资);
DEBT:有欠款(垫资支付);
REPAYMENT:(已还款)
商品信息 description string 示例值: 初级中学午餐
字符字节限制: [0, 128]
商品信息
商户附加信息 attach string 示例值: id=1
字符字节限制: [0, 128]
商品附加描述,长度不大于128
支付成功时间 success_time string 示例值: 2015-05-20T13:29:35.120+08:00
字符字节限制: [0, 32]
使用ISO 8601所定义的格式
微信订单号 transaction_id string 示例值: 4200032343298099898
字符字节限制: [0, 32]
支付成功才返回
还款微信订单号 repayment_transaction_id string 示例值: 1217752501201407033233368018
字符字节限制: [0, 32]
订单为垫资支付且用户已还款时产生的微信交易订单号,当欠款单状态为REPAYMENT时返回
商户订单号 out_trade_no string 示例值: 1217752501201407033233368018
字符字节限制: [0, 32]
商户订单号

payer定义如下:

字段名 变量名 类型 必填 示例 描述
公众下的openid sp_openid string 示例值: fefewfwe
字符字节限制: [0, 128]
付款用户信息
子公众下的openid sub_openid string 示例值: fefewfwe
字符字节限制: [0, 128]
付款用户信息

amount定义如下:

字段名 变量名 类型 必填 示例 描述
订单金额 total int64 示例值: 3 金额,单位:分
用户支付金额 pay_total int64 示例值: 3 金额,单位:分
货币类型 currency string 示例值: CNY 货币类型,目前只支持人民币
用户支付货币类型 pay_currency string 示例值: CNY 货币类型,目前只支持人民币

返回码处理建议

httpcode 错误码 处理方式
200 请求正确处理,应该判断订单状态 “SUCCESS”-支付成功(支付成功无需处理)
“REFUND”-转入退款(支付成功无需处理)
“NOTPAY”-未支付(24小时内参数不变重试扣款)
“CLOSED"-已关闭(参数不变换单号重试)
“REVOKED”-已撤销(参数不变换单号重试)
“USERPAYING”-用户支付中(24小时内参数不变重试扣款)
“PAYERROR”-支付失败(换单号重试)
500 SYSTEM_ERROR 请稍后重试,建议同一笔订单每天重试不要超过5次,频繁重试会导致该用户无法扣款
400 PARAM_ERROR 参数错误,请检查参数
400 INVALID_REQUEST 目前子商户未开通权限、凭证已经使用过并且扣款成功、请求参数和凭证信息不一致、凭证正在扣款又换单号重试、重入请求变更了参数都会返回该错误码,表示请求参数符合格式,但不符合业务规则,需要服务商定位问题并修正代码
429 RATELIMIT_EXCEEDED 请求达到速率限制

# 4.15 获取还款链接接口

接口定义
POST https://api.mch.weixin.qq.com/v3/offlineface/repayment-url

请求参数

字段名 变量名 类型 必填 示例 描述
商户用户ID out_user_id string 123456 欠款用户在商户侧的唯一标识
机构ID organization_id string Obeeeee 机构id

返回结果

状态码 错误码 错误说明
200 请求正确处理 获取authinfo成功
500 SYSTEM_ERROR 请稍后重试
400 PARAM_ERROR 参数错误,请检查参数
400 INVALID_REQUEST 表示请求参数符合格式,但不符合业务规则
429 RATELIMIT_EXCEEDED 请求达到速率限制
字段名 变量名 类型 必填 示例 描述
还款链接 repayment_url string / 还款小程序跳转链接,仅支持微信环境下打开
链接过期时间 expire_at string 2021-05-30T12:13:50+08:00 还款链接的过期时间,到期后还款链接将无法跳转

# 5. 非刷脸交易上报

开发集成后,还需要完成APP里的微信非刷脸交易上报 , 否则会影响审批。

详情请见交易上报(reportOrder)

上次更新: 11/14/2022, 3:01:17 PM