目录:

  1. 流程介绍
    1.1 支付宝自助机刷脸支付交互图
    1.2 支付宝自助机刷脸核身交互图
  2. 接入指引
    2.1 准备工作
    2.2 接口调用规范
    2.2.1 请求说明
  3. 刷脸付
    3.1 接入细节
    3.2 获取刷脸所需的设备信息
    3.3 刷脸初始化
    3.4 唤起人脸识别
    3.5 调用收单接口完成支付
    3.6 交易结果查询接口
  4. 刷脸核身
    4.1 接入细节
    4.2 唤起用户授权
    4.3 支付宝人脸核身获取用户详细信息
  5. 参考文档
  6. 修订记录

1. 流程介绍

1.1 支付宝自助机刷脸支付交互图

  1. 获取刷脸所需的设备信息【自助机】商户pid+服务商pid+服务商appid->metainfo
  2. 刷脸初始化【聚合支付平台】metainfo->zim_id
  3. 唤起人脸识别【自助机】zim_id->ftoken
  4. 调用收单接口完成支付【聚合支付平台】auth_code=ftoken

1.2 支付宝自助机刷脸核身交互图

(1)授权获取用户信息方案

  1. 获取刷脸所需的设备信息【自助机】商户pid+服务商pid+服务商appid->metainfo
  2. 刷脸初始化【聚合支付平台】metainfo->zim_id
  3. 唤起人脸识别【自助机】zim_id->ftoken
  4. 通过ftoken唤起用户授权【自助机】ftoken->auth_code
  5. 获取用户信息【聚合支付平台】auth_code->userinfo


(2)用户填写信息验证方案

  1. 用户填写身份证和姓名
  2. 获取刷脸所需的设备信息【自助机】商户pid+服务商pid+服务商appid->metainfo
  3. 刷脸初始化【聚合支付平台】把第一步的信息放入metainfo的extInfo中->zim_id
  4. 唤起人脸识别【自助机】zim_id->ftoken
  5. 刷脸认证后返回识别结果
    faceverify

2. 接入指引

2.1 准备工作

第一步、获取开发者数据

调用聚合支付平台接口,需要与平台商务对接后,获取开发者ID(developId),密钥(privateKey),公钥(publicKey)和对称密钥(desKey),这些参数让商户拥有调用平台接口的权限,对请求的数据进行加密以保证数据的安全性。

  • 开发者ID(developerId):
      developerId在所有的请求中都需要传入,与密钥公钥信息相对应,鉴别请求是否是由平台商户发起。
  • 密钥(privateKey):
      密钥在接口请求中用于对数据进行RSA加密,生成签名sign。
  • 公钥(publicKey):
      公钥用于对签名进行解密
  • 对称密钥(desKey):
      在线上支付中,<body>标签的中的参数,需要通过des进行对称加密,得到密文进行请求。

第二步、获取平台商户号

每个商户对接聚合支付平台,在第三方平台想要拥有的支付能力,需要在支付宝或者微信签约对应的支付方式,平台的商务会为每个商户分配一个平台商户号(merchantNo),该商户号账户下所有的交易流水都会进入到对应的支付宝和微信的账户下,并且平台账单流水都是以商户号进行隔离,这是一个非常重要的参数。
由于自助机通过获取设备信息,需要传入平台信息,
因此,除了上述参数,还需要拿到以下信息:
平台应用id(appId)
平台pid(partnerId)

第三步、下载加解密sdk和demo

2.2 接口调用规范

2.2.1 请求说明
参数 类型 是否必填 最大长度 描述 示例
data String 300 请求参数转为xml格式 <xml><paytype>2</paytype><merchant_no>10000</merchant_no></xml>
developerId String 10 开发者id 12345
funcId String 20 功能码 P7001
sign String 100 将公共参数以“参数名”ASCII码顺序排序拼接成新字符串(参数名ASCII码从小到大排序(字典序))得到:“data=value1&developerId=value2&funcId=value3”,再将新的字符串经过RSA签名得到签名后的字符串 Sa/hb9jaTZZZq89mN62DDooLv/YTvfE9ayrbzgOMsucfIPZfJGmhUia6YWK8vQ5/NQana3Pub7BDswEenm0sBg==
  • 公共返回参数说明:
参数 类型 是否必填 最大长度 描述 示例
retCode String 30 0000:表示接口业务调用正常,9999:表示处理失败,如参数错误,验签失败等(注:retCode并不表示交易行为成功或失败,某笔交易是否成功请根据对应接口返回报文的状态字段来判定 0000
retMsg String 100 接口调用异常返回信息 验签失败

3. 刷脸付

3.1 接入细节

3.2 获取刷脸所需的设备信息

  • 说明:调用接口zolozGetMetaInfo采集刷脸所需的设备信息并完成刷脸的准备工作。如果zolozGetMetaInfo返回成功结果,则请求商户服务端调用支付宝开放平台的人脸初始化接口。

  • 示例:

    private void smilePay() {
      //调用zolozGetMetaInfo完成设备信息采集
      zoloz.zolozGetMetaInfo(mockInfo(), new ZolozCallback() {
    
      // 解析zolozGetMetaInfo返回的结果,如果成功,则请求商户服务端调用人脸初始化接口
      @Override
      public void response(Map smileToPayResponse) {
          if (smileToPayResponse != null) {
              String code = (String)smileToPayResponse.get("code");
              String metaInfo = (String)smileToPayResponse.get("metainfo");
    
              if (CODE_SUCCESS.equalsIgnoreCase(code) && metaInfo != null) {
                 // 将metaInfo发送给商户服务端,由商户服务端发起刷脸初始化OpenAPI的调用
                  ...
              }
      }
    
     /**
       * mock数据,真实商户请填写真实信息.
       */
      private Map mockInfo() {
          Map merchantInfo = new HashMap();
          //以下信息请根据真实情况填写
          //商户 Pid
          merchantInfo.put("merchantId", partnerId);
          //ISV PID
          merchantInfo.put("partnerId", partnerId);
          //添加刷脸付功能的appid
          merchantInfo.put("appId", appId);
          //机具编号,便于关联商家管理的机具
          merchantInfo.put("deviceNum", "TEST_ZOLOZ_TEST");
          //商户的门店编号
          merchantInfo.put("storeCode", "TEST");
          //支付宝门店编号
          merchantInfo.put("alipayStoreCode", "TEST");
    
          return merchantInfo;
      }
参数 说明
merchantId 必填项,签约商户的pid。以2088开头
partnerId 可选项,ISV的pid。对于自用型商户,填写签约商户的pid,和merchantId保持一致
appId 可选项,支付宝分配给开发者的应用ID,和当面付请求的appid保持一致。
deviceNum 必填项,商户机具终端编号,和当面付请求的terminal_id 保持一致
storeCode 可选,商户门店编号,和当面付请求的store_id保持一致。
alipayStoreCode 可选,支付宝内部门店编号,和当面付请求中的alipay_store_id保持一致。
  • 响应参数:
    关键出參:回调函数返回的metainfo对象结构,该对象中的参数请不需要
    做任何值的修改,否则会导致后续刷脸出错。请直接传给商户服务端作为下一步调用的入參。
参数 说明
apdidToken 设备指纹
appName 应用名称
appVersion 应用版本
bioMetaInfo 生物信息
osVersion 系统版本
machineInfo 设备硬件相关信息
merchantInfo 商户相关信息
remoteLogID 刷脸调用的事务ID
extInfo 扩展参数,用于商户服务端传入信息

extInfo信息介绍

参数 说明
certNo 身份证号 当bizType=1时使用
certName 身份证姓名 当bizType=1时使用
certType IDCARD 当bizType=1时使用
bizType 1身份核验场景、4刷脸核身(手机号码)

例子:

JSONObject extInfo = new JSONObject();

/* start: 如果是1:1刷脸认证(姓名+身份证号),请加入以下代码 */
extInfo.put("certNo", "身份证号"); //必填,当前被认证用户的身份证号
extInfo.put("certName", "身份证姓名");//必填,当前被认证用户的姓名(保持和身份证一致)
extInfo.put("certType", "IDCARD"); //写为IDCARD,表明身份证
extInfo.put("bizType", "1"); //固定写为1,表明1:1身份核验场景
/* end: -------------------------------------------- */

/* start: 如果是1:1刷脸认证(手机号),请加入以下代码 */
extInfo.put("bizType", "4"); //固定写为4,表明1:1刷脸核身(手机号)场景
/* end: -------------------------------------- */

zimmetainfo.put("extInfo", extInfo);

3.3 刷脸初始化

  • 功能码:P5001
  • 接口说明:通过该接口初始化人脸初始化参数
  • 请求参数:<xml>
参数 名称 类型 长度 是否必填 说明 示例
paytype 支付渠道 String 2-支付宝 3-微信
deviceId 微信设备Id String 微信支付必填 微信人脸支付设备序列号
meta_info 透传体 String 获取刷脸所需的设备信息返回的metainfo
微信SDK返回的rawData
amt 订单金额 String 32 订单金额,值为double类型 0.01
merchant_no 收款商户号 String 32 商户号
transType 交易类型 String 32 7-刷脸支付
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
return_code 返回状态码 String 16 SUCCESS/OK代表成功 FAIL=代表失败 SUCCESS
return_msg 返回信息 String 128 返回信息 OK
zim_id 刷脸调用的标识,将作为下一步zolozVerify接口的入參 String 刷脸调用的标识
zim_init_client_data 支付宝 :刷脸的下发协议数据,将作为下一步zolozVerify接口的入參
微信: authInfo 信息 SDK调用凭证。用于调用SDK的人脸识别接口。为便于xml文件解析,authInfo进行了URLEncode,取出时可能需要进行相应的URLDecode操作
String 刷脸的下发协议数据
  • java请求示例:

    String xml = "<xml>" +
                  "<meta_info></meta_info>" +
                  "<merchant_no>xxxxxx</merchant_no>" +
                  "</xml>";
        List<NameValuePair> list = new ArrayList<NameValuePair>();
        NameValuePair valu1 = new BasicNameValuePair("data",data);
        NameValuePair valu2 = new BasicNameValuePair("developerId",[your developerId]);
        NameValuePair valu3 = new BasicNameValuePair("funcId","P5001");
        String privateKey = [your privateKey];
        String signData = "data="+data+"&developerId=[your developerId]&funcId=P5001";
        String sign = SecurityUtil.signRSA(signData,privateKey,"utf-8");
        NameValuePair valu4 = new BasicNameValuePair("sign",sign);
        list.add(valu1);
        list.add(valu2);
        list.add(valu3);
        list.add(valu4);
        String xml = null;
        try {
            CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://offlinetest.bsoftpay.com/gatewayOffline/pay/offline/execute").setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8)).build());
            xml = EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(xml);
  • 返回示例:

    developerId=31331&funcId=P5001&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <xml>
     <return_code>SUCCESS</return_code>
     <return_msg>OK</return_msg>
     <zim_id></zim_id>
     <zim_init_client_data></zim_init_client_data>
    </xml>
    &sign=Seko5j5kYUs1Vpmpon03IgX7GqiNYWvOkhcUq7alPneOGWSjNPuY3QeXMzUSTBiMC1WQGVwlK+TBPzQeDvvUnQ==

    3.4 唤起人脸识别

  • 说明:调用zolozVerify接口唤起人脸采集页面并完成比对过程。如果认证成功,将返回一个ftoken。该ftoken用于后续查询被认证用户的信息。

  • 示例:

    //将上一步中initialize接口返回的zim_init_client_data对象和zim_id作为入參
    Map params = new HashMap();
    params.put("zim.init.resp", protocal);
    可选:smile_mode用于指定选择刷脸模式,值为int类型,0:主屏幕显示(默认值);1:双面屏机具,副屏幕显示  
    params.put("smile_mode", 0);
    zoloz.zolozVerify(zimId, params, new ZolozCallback() {
      @Override
      public void response(final Map smileToPayResponse) {
          if (smileToPayResponse != null) {
              String code = (String)smileToPayResponse.get("code");
              String fToken = (String)smileToPayResponse.get("ftoken");
              String subCode = (String)smileToPayResponse.get("subCode");
              String msg = (String)smileToPayResponse.get("msg");
              //刷脸成功
              if (CODE_SUCCESS.equalsIgnoreCase(code) && fToken != null) {
              }
          }
      }
    }
  • 返回结果示例:
    注意:在result对象中会返回当前认证用户的支付宝UID,这个UID是客户端接口返回的结果,并不安全。如果需要依赖UID进行业务决策,请不要使用这个UID数据。请通过服务端ftoken查询接口(query)得到可信的UID

    {
        "code":"返回码",
        "subCode":"二级返回码",
        "msg":"返回信息", 
        "ftoken":"ftoken",//用来支付或完成其他操作
        "result":{
          "alipayUid":"alipayUid", //支付宝账户的uid
        }
    }
  • 关键入参:

参数名称 参数类型 是否必填 参数说明
zimId String 人脸初始化接口返回的zimId, 其中包含了唤起人脸验证的关键参数
params Map zim.init.resp 必填,调用服务初始化返回的结果中的协议内容
phone_number 可选,用于会员刷脸付方案。填入用户登录会员系统的手机号
smile_mode 可选,用于指定选择刷脸模式,值为int类型,0: 主屏幕显示(默认值);1:双面屏机具,副屏幕显示
  • 关键出参:
参数名称 描述
zimId 错误码,如果刷脸认证成功返回,则为CODE_SUCCESS。常见错误码见下面表格
msg 返回信息
subCode 二级返回码
ftoken 标识刷脸认证成功,作为查询接口的入參 有效期2分钟
result alipayUid被认证用户的支付宝账户UID

3.5 调用收单接口完成支付

  • 功能码:P7001
  • 接口说明:当自助机调用唤起人脸识别接口完成后,会得到ftoken,用该ftoken作为授权码auth_code,传入聚合支付平台的支付接口(P7001)进行支付。调用支付接口,需要注意以下事项:
  1. merchant_no传入的是平台的商户号,不是支付宝商户的商户号;
  2. paytype支付渠道请选择2=支付宝
  3. trade_type交易类型,选择7=刷脸付
  4. auth_code授权码,传入ftoken
  5. scene_type场景信息,传入1=自助机
  6. terminal_id商户机具终端编号,请与获取设备信息接口入参deviceNum保持一致
  7. store_id商户门店编号,请与获取设备信息接口入参storeCode保持一致
  8. alipay_store_id支付宝内部门店编号,请与获取设备信息接口入参alipayStoreCode保持一致
  • 请求参数:<xml>
参数 名称 类型 长度 是否必填 说明 示例
treatment_id 诊疗卡卡号 String 30 患者的诊疗卡卡号 123
merchant_no 收款商户号 String 30 创业聚合支付系统为医院分配的平台商户号 809900000001
username 支付者姓名 String 30 付款者姓名 张三
order_no 业务单号 String 30 商户业务系统的唯一订单号 BX20190722902141
paytype 支付渠道 String 2 2=支付宝 2
trade_type 交易类型 String 2 7=刷脸付 1
total_amt 支付金额 Price 20.2 以元为单位 0.01
spbill_create_ip 用户IP String 10 客户端实际ip(微信需要) 183.156.115.113
order_subject 商品标题 String 150 如:门诊、住院预交、住院结算、自助缴费等 门诊
order_detail 商品描述 String 300 如:门诊挂号、门诊结算、住院预交、住院结算、自助挂号、自助结算、自助住院预交等 门诊挂号
sub_merchant 分店号 String 30 商户内部区分订单字段 001
paytimeout 订单超时时间 String 3 单位是: m (分钟) 如果不填,默认是 6分钟,如果填,必须大于5分钟 6
mobile 手机号码 String 15 用户手机号 13211112222
auth_code 授权码 String 128 传入ftoken 134692901956119825
scene_type 场景类型 String 1 1=自助机 1
terminal_id 商户机具终端编号 String 1 与获取设备信息接口传入deviceNum字段保持一致 NJ_T_001
store_id 商户门店编号 String 1 与获取设备信息接口入参storeCode保持一致 NJ_001
alipay_store_id 支付宝内部门店编号 String 1 与获取设备信息接口入参alipayStoreCode保持一致
remark 备注 String 200 备注
big_merchant_no 统一商户号 String 30 流水转入统收商户中(不建议使用,对账无法区分)
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
return_code 返回状态码 String 16 SUCCESS/OK代表成功 FAIL=代表失败 WAIT=待支付 不能以此作为支付成功标志,支付结果以status为准 SUCCESS
return_msg 返回信息 String 128 返回信息 OK
code_url 二维码串 String 500 扫码付时返回
status 支付状态 String 2 1=成功;0=支付中 需要调用查询接口轮询查询订单状态 刷卡支付时使用 1
pay_orderno 支付渠道流水号 String 32 刷卡支付时使用 4200000376201908224052992001
order_no 平台流水号 String 32 刷卡支付时使用 34411000
out_tradeno 业务单号 String 32 刷卡支付时使用 BX20190722902141
time_end 支付完成时间 String 32 刷卡支付时使用(yyyyMMddHHmmss) 20190722205306
amt 实际支付金额 Price 16.2 刷卡支付时使用 0.01
receipt_amount 商户收到的金额 Price 16.2 刷卡支付时使用(相当于订单支付金额) 0.01
  • Java请求示例:
    String data = "<xml>" +
                  "<treatment_id>123123123123</treatment_id>" +
                  "<merchant_no>1001003</merchant_no>" +
                  "<username>测试者</username>" +
                  "<order_no>"+ "xw20190722001"+"</order_no>" +
                  "<paytype>3</paytype>" +
                  "<trade_type>2</trade_type>" +
                  "<total_amt>0.01</total_amt>" +
                  "<spbill_create_ip>192.168.11.1</spbill_create_ip>" +
                  "<order_subject>测试</order_subject>" +
                  "<order_detail>测试</order_detail>" +
                  "<auth_code>130195331105619585</auth_code>" +
                  "</xml>";
          List<NameValuePair> list = new ArrayList<NameValuePair>();
          NameValuePair valu1 = new BasicNameValuePair("data",data);
          NameValuePair valu2 = new BasicNameValuePair("developerId",[your developerId]);
          NameValuePair valu3 = new BasicNameValuePair("funcId","P7001");
          String privateKey = [your privateKey];
          String signData = "data="+data+"&developerId=[your developerId]&funcId=P7001";
          String sign = SecurityUtil.signRSA(signData,privateKey,"utf-8");
          NameValuePair valu4 = new BasicNameValuePair("sign",sign);
          list.add(valu1);
          list.add(valu2);
          list.add(valu3);
          list.add(valu4);
          String xml = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://offlinetest.bsoftpay.com/gatewayOffline/pay/offline/execute").setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8)).build());
              xml = EntityUtils.toString(response.getEntity());
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(xml);
  • 返回示例:
    developerId=12345&funcId=P7001&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <xml>
    <return_code>SUCCESS</return_code>
    <return_msg>OK</return_msg>
    <status>1</status>
    <pay_orderno>4200000376201907220000000000</pay_orderno>
    <order_no>34411000</order_no>
    <out_tradeno>WX15637998177239200001</out_tradeno>
    <time_end>20190722205306</time_end>
    <amt>0.01</amt>
    <receipt_amount>0.01</receipt_amount>
    </xml>
    &sign=Apu4i49RBQkh94n5BVEA/Ao35tjfT8BsTPA9fOqKUmbKJ37Pszfi0sS9R15OLEpXJYo6p2v+uw1fr/BE+PSxHg==
  • 异常返回示例:
    developerId=12345&funcId=P7001&retCode=9999&retMsg=请扫描微信支付授权码(以10/11/12/13/14/15为前缀的18位数字)&sign=XD1unE4I2pM/jWMXy1o7NwVB2H3yfkmxluH2qz3xRt+mB8VQNSLhKnz79+5PuRfz9Q4y44CKCyL7S21iQzOHbg==
  • 注意:签名sign生成之后,在请求发送之前,需要对签名字符串进行urlEncode编码,否则字符串在传递过程中可能会不完整,从而导致“验证签名失败”

3.6 交易结果查询接口

  • 功能码:P2005
  • 接口说明:通过该接口获取某个订单的支付结果
  • 请求参数:<Data>
参数 名称 类型 长度 是否必填 说明 示例
order_no 业务单号 String 32 商户内部业务单号 WX2019072200001
merchant_no 收款商户号 String 32 商户号 809900000001
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
TradeNo 平台流水号 String 32 聚合支付平台流水号 34411000
PayTradeNo 渠道流水号 String 32 各个支付渠道返回的流水号 4200000376201907220000000000
OrderNo 业务单号 String 32 商户内部业务单号 WX2019072200001
Amt 实际支付金额 Price 16.2 用户实际付款金额 0.01
PayTime 实际支付时间 String 16 yyyy-MM-dd hh:mm:ss 2019-07-22 21:37:31
PayStatus 支付状态 String 6 0=未支付;1=支付成功;2=支付失败;-1=关闭或撤销 1
receipt_amount 商户收到的金额 Price 16.2 相当于订单支付金额 0.01
  • JAVA请求示例:
    String data = "<Data>" +
                  "<order_no>WX2019072200001</order_no>\n" +
                  "<merchant_no>809900000001</merchant_no>\n"+
                  "</Data>";
          List<NameValuePair> list = new ArrayList<NameValuePair>();
          NameValuePair valu1 = new BasicNameValuePair("data",data);
          NameValuePair valu2 = new BasicNameValuePair("developerId","[your developerId]");
          NameValuePair valu3 = new BasicNameValuePair("funcId","P2005");
          String privateKey = [your privateKey];
          String signData = "data="+data+"&developerId=[your developerId]&funcId=P2005";
          String sign = SecurityUtil.signRSA(signData,privateKey,"utf-8");
          NameValuePair valu4 = new BasicNameValuePair("sign",sign);
          list.add(valu1);
          list.add(valu2);
          list.add(valu3);
          list.add(valu4);
          String xml = null;
          try {
              CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://offlinetest.bsoftpay.com/gatewayOffline/pay/offline/execute").setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8)).build());
              xml = EntityUtils.toString(response.getEntity());
          } catch (Exception e) {
              e.printStackTrace();
          }
          System.out.println(xml);
  • 返回示例:
    developerId=66337&funcId=P2005&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <Data>
    <TradeNo>34411000</TradeNo>
    <PayTradeNo>4200000376201907220000000000</PayTradeNo>
    <OrderNo>WX2019072200001</OrderNo>
    <Amt>0.01</Amt>
    <receipt_amount>0.01</receipt_amount>
    <PayTime>2019-07-22 21:37:31</PayTime>
    <PayStatus>1</PayStatus>
    </Data>
    &sign=JxUbXFPS4Kp3bS9ipmznDoAwBd3TzLX4Df8xd5VFR97Z1Kyb5XiJNxZ4LXA1RIlOafm+BmmnPXZXDfykss3geg==
  • 注意: P2005功能中请求参数是用<Data></Data>包围,不是<xml></xml>

    4. 人脸核身

    4.1 接入细节

  • 接口说明:按照刷脸流程1-2-3,同刷脸支付。细节见文档
    方案一(传入身份证进行认证):
    https://docs.alipay.com/pre-open/20171214171953173616/gwqlk0
    方案二(获取用户授权信息):
    https://docs.open.alipay.com/289/105656

    4.2 唤起用户授权

  • 接口说明:扫脸核身完成后进行用户授权接入获取用户基础信息身份证信息需要找支付宝客户经理申请。解决方案技术实现如下
  1. 扫码授权请求拼接规则需要用户扫码登录
参数说明 是否必须 说明
app_id 开发者应用的app_id; 相同支付宝账号下,不同的app_id获取的token切忌混用。
redirect_uri 授权回调地址,是经过URLENCODE转义 的url链接(url必须以http或者https开头); 在请求之前,开发者需要先到开发者中心对应应用内,配置授权回调地址。 redirect_uri与应用配置的授权回调地址域名部分必须一致。http%3A%2F%2Fpay.bsoftpay.com%3A53503%2FtoAuthPage
scopes 接口权限值,目前只支持auth_user(获取用户信息、网站支付宝登录)、auth_base(用户信息授权)、auth_ecard(商户会员卡)、auth_invoice_info(支付宝闪电开票)、auth_puc_charge(生活缴费)五个值;多个scope时用”,”分隔,如scope为”auth_user,auth_ecard”时,此时获取到的access_token,既可以用来获取用户信息,又可以给用户发送会员卡。
state 商户自定义参数,用户授权后,重定向到redirect_uri时会原样回传给商户。 为防止CSRF攻击,建议开发者请求授权时传入state参数,该参数要做到既不可预测,又可以证明客户端和当前第三方网站的登录认证状态存在关联。只允许base64字符(长度小于等于100)
  • 拼接样例:
    https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=APPID&scope=SCOPE&redirect_uri=ENCODED_URL
    注意:各个参数需要做urlEncode,redirect_uri参数尽量放置在最后一位
    授权时如遇”人气大爆发”提示,可通过客户端开发者模式查看报错原因
  1. 刷脸授权请求拼接规则
参数说明 是否必须 说明
app_id 开发者应用的app_id; 相同支付宝账号下,不同的app_id获取的token切忌混用。
redirect_uri 授权回调地址(url必须以http或者https开头); 在请求之前,开发者需要先到开发者中心对应应用内,配置授权回调地址。 redirect_uri与应用配置的授权回调地址域名部分必须一致。http://pay.bsoftpay.com:53503/toAuthPage
scopes 接口权限值,目前只支持auth_user、auth_base、auth_zhima、auth_ecard、auth_certdoc五个值;多个scope时用”,”分隔,如scope为“auth_user,auth_certdoc”
state 商户自定义参数,用户授权后,重定向到redirect_uri时会原样回传给商户。 为防止CSRF攻击,建议开发者请求授权时传入state参数,该参数要做到既不可预测,又可以证明客户端和当前第三方网站的登录认证状态存在关联。只允许base64字符(长度小于等于100)
auth_type 刷脸:FACE_REC_OAUTH
ftoken 人脸token
  • 拼接样例:
    https://authweb.alipay.com/auth?auth_type=FACE_REC_OAUTH&ftoken=XXXXX&app_id=&scope=xxxx&state=xxx&redirect_uri=http://pay.bsoftpay.com:53503/toAuthPage
    注意:授权时如遇”人气大爆发”提示,可通过客户端开发者模式查看报错原因,常见原因为Ftoken过期,回调地址异常等
  1. 获取auth_code
    当用户授权成功后,会跳转至开发者定义的回调页面,支付宝会在回调页面请求中加入参数,包括auth_code、app_id、scope等,需要注意的是支付宝仅保证auth_code、app_id以及scope参数的有效性。支付宝请求开发者回调页面示例如下:
    http://pay.bsoftpay.com:53503/toAuthPage?app_id=2014101500013658&scope=auth_user&state=XXXX&auth_code=ca34ea491e7146cc87d25fca24c4cD11

    4.3 支付宝人脸核身获取用户详细信息

  • 功能码:P5002
  • 接口说明:通过该接口获取用户详细信息
  • 请求参数:<xml>
参数 名称 类型 长度 是否必填 说明 示例
auth_code 授权码 String 32 授权码 ca34ea491e7146cc87d25fca24c4cD11
merchant_no 收款商户号 String 32 商户号
  • 响应参数:
参数 名称 类型 长度 是否必输 说明 示例
return_code 返回状态码 String 16 SUCCESS/OK代表成功 FAIL=代表失败 SUCCESS
return_msg 返回信息 String 128 返回信息 OK
user_id 支付宝用户的userId String 2088102104794936
avatar 用户头像地址 String http://tfsimg.alipay.com/images/partner/T1uIxXXbpXXXXXXXX
province 省份名称 String 安徽省
city 市名称。 String 安庆
nick_name 用户昵称 String 用户昵称 支付宝小二
is_student_certified 是否是学生 String 是否是学生 T
user_type 用户类型 String 用户类型(1/2) 1代表公司账户2代表个人账户 1
user_status 用户状态 String 用户状态(Q/T/B/W)。Q代表快速注册用户 T代表已认证用户 B代表被冻结账户 W代表已注册,未激活的账户 T
is_certified 是否通过实名认证。 String T是通过 F是没有实名认证 F
gender 性别 String 【注意】只有is_certified为T的时候才有意义,否则不保证准确性. 性别(f:女性;m:男性)。 f
user_name 用户真实姓名 String
mobile 手机号码 String
cert_no 身份证 String
cert_type 证件类型 String
  • java请求示例:
    String xml = "<xml>" +
                  "<auth_code>ftoken</auth_code>" +
                  "<merchant_no>xxxxxxx</merchant_no>" +
                  "</xml>";
        List<NameValuePair> list = new ArrayList<NameValuePair>();
        NameValuePair valu1 = new BasicNameValuePair("data",data);
        NameValuePair valu2 = new BasicNameValuePair("developerId",[your developerId]);
        NameValuePair valu3 = new BasicNameValuePair("funcId","P5002");
        String privateKey = [your privateKey];
        String signData = "data="+data+"&developerId=[your developerId]&funcId=P5002";
        String sign = SecurityUtil.signRSA(signData,privateKey,"utf-8");
        NameValuePair valu4 = new BasicNameValuePair("sign",sign);
        list.add(valu1);
        list.add(valu2);
        list.add(valu3);
        list.add(valu4);
        String xml = null;
        try {
            CloseableHttpResponse response = HttpClients.custom().build().execute(RequestBuilder.post().setUri("http://offlinetest.bsoftpay.com/gatewayOffline/pay/offline/execute").setEntity(new UrlEncodedFormEntity(list, Consts.UTF_8)).build());
            xml = EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(xml);
  • 返回示例:
    developerId=31331&funcId=P5002&retCode=0000&retMsg= &data=<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <xml>
     <return_code>SUCCESS</return_code>
     <return_msg>OK</return_msg>
     <user_id></user_id>
     <avatar></avatar>
     <province></province>
     <city></city>
     <nick_name></nick_name>
     <is_student_certified></is_student_certified>
     <user_type></user_type>
     <user_status></user_status>
     <is_certified></is_certified>
     <gender></gender>
     <user_name></user_name>
     <mobile></mobile>
     <cert_no></cert_no>
     <cert_type></cert_type>
    </xml>
    &sign=Seko5j5kYUs1Vpmpon03IgX7GqiNYWvOkhcUq7alPneOGWSjNPuY3QeXMzUSTBiMC1WQGVwlK+TBPzQeDvvUnQ==

5. 参考文档

刷脸支付-支付宝官方文档:https://docs.open.alipay.com/20180402104715814204/cgxcze/
扫码核身-支付宝官方文档:https://docs.open.alipay.com/289/105656
刷脸核身-支付宝官方文档:https://www.yuque.com/fmsprh/ippl9x/hq0kds

6. 修订记录

日期 修订内容 修订人
2019-11-25 新增刷脸付文档 邓辉
文档更新时间: 2023-08-29 13:58   作者:邓辉