Java支付宝身份验证接口接入指南

最近公司项目有人脸身份核验的需求,首先就想到了支付宝的身份验证接口,于是就需要看支付宝的开放api文档,这里就有些坑,然后就本次接入遇到的坑,做个整理。(基于web网页)

一.文档查找

我们要用的接口就图中的三个:

java 应用认证 java身份认证_java 应用认证

但是不推荐看上图中的api文档,不知什么原因,这三个接口的传参及返回值有些混乱,导致无法顺利接入。

推荐看这个地址的文档:https://docs.open.alipay.com/20181012100420932508

或者看我现在写的这篇(根据上面的这个文档整理的)。

二.前期准备

首先确保你有一个企业支付宝账号,身份验证需要签约商户,要企业支付宝开发者才能调用。将你手中的企业支付宝入驻到支付宝开放平台。

1.创建应用

要在您的应用中接入身份验证能力,您需要登录 开放平台控制台,在控制台创建您的应用,应用审核通过后会生成应用唯一标识(APPID),并且可以申请开通开放产品使用权限。通过 APPID 您的应用才能调用开放产品的接口能力。需要详细了解开放平台创建应用步骤请参见 创建应用。

2.配置应用

添加能力

应用创建完成后,系统会自动跳转到应用详情页面。开发者可以点击 添加能力 选择 身份验证 来添加能力。

java 应用认证 java身份认证_java_02

这里需要说明一下:身份验证能力添加好了后,需要关联,点击商家中心,关联你的应用。

配置密钥

为了保证交易双方(商户和支付宝)的身份和数据安全,开发者在调用接口前,需要配置双方密钥,对交易数据进行双方校验。RSA 密钥包含应用私钥(APP_PRIVATE_KEY)、应用公钥(APP_PUBLIC_KEY)。生成密钥后,开发者需要在开放平台开发者中心进行密钥配置,配置完成后可以获取支付宝公钥(ALIPAY_PUBLIC_KEY),配置的详细步骤请参见 配置密钥。您还可以通过观看 快速签名教程 学习密钥的配置。

这里需要说明一下:使用支付宝开放平台开发助手生成的是应用私钥(APP_PRIVATE_KEY)、应用公钥(APP_PUBLIC_KEY) 需要在你的应用控制台进行密钥配置,然后得到支付宝公钥(ALIPAY_PUBLIC_KEY)。后续接入参数要用到的就是应用私钥(APP_PRIVATE_KEY)和支付宝公钥(ALIPAY_PUBLIC_KEY)

上线应用并签约

开发者在添加功能和配置密钥后,即可将应用提交审核,预计会有一个工作日的审核时间,请耐心等待,详细步骤可参考 上线应用。

应用上线完成后,要使用身份验证能力,您还需要完成签约能力才能生效。请点击功能列表右侧 签约,提交相关信息;完成签约后,需要一个工作日左右的时间审核(审批结果会以短信和邮件形式告知),待审核完毕后,功能的状态会变成 已生效,您的应用即可使用 身份验证 能力。

说明:身份验证暂不支持第三方 ISV 代签约开通。

三.接入接口

1.引入sdk依赖

引入下面的依赖就可以了:

<dependency>
    <groupId>com.alipay.sdk</groupId>
    <artifactId>alipay-sdk-java</artifactId>
    <version>3.7.110.ALL</version>
</dependency>

2.在配置文件中配置属性:

ali:
  appId: 你的应用APPID
  rsaPrivateKey: 你的应用私钥(APP_PRIVATE_KEY)
  alipayPublicKey: 你的支付宝公钥(ALIPAY_PUBLIC_KEY)
  charset: utf-8
  format: json
  signType: RSA2
  gatewayUrl: https://openapi.alipay.com/gateway.do

3.读取配置并加载AlipayClient

**
 * 读取配置文件阿里配置
 * @Author zjl
 * @Date 2020/9/15 9:15
 */
@Data
@ConfigurationProperties(prefix = "ali")
public class AliProperties {
    public String appId;
    // 商户私钥,您的PKCS8格式RSA2私钥
    public String rsaPrivateKey;
    // 对应APPID下的支付宝公钥
    public String alipayPublicKey;
    // 支付宝网关 
    public String gatewayUrl;
    // 字符编码格式
    public String charset;
    //格式
    public String format;
    // 签名方式
    public String signType;
}


/**
 * 开启支付宝客户端
 * @Author zjl
 * @Date 2020/9/15 9:33
 */
@Configuration
@EnableConfigurationProperties(AliProperties.class)
public class AliCilent {

    @Bean
    public AlipayClient alipayClient(AliProperties pro) {
        return new DefaultAlipayClient(pro.getGatewayUrl(), pro.getAppId(), pro.getRsaPrivateKey(),
                pro.getFormat(), pro.getCharset(), pro.getAlipayPublicKey(), pro.getSignType()
        );
    }

}

4.身份认证:

@Autowired
 private AlipayClient alipayClient;
 
 1.初始化身份认证
 	/**
     * 初始化身份认证
     *
     * @param realName 真实姓名
     * @param idNum    身份证号码
     * @return
     */
    public String authInitialize(String realName, String idNum) {
        AlipayUserCertifyOpenInitializeRequest request = new AlipayUserCertifyOpenInitializeRequest();

        //构造身份信息json对象  JSONObject 阿里的fastjson
        JSONObject identityObj = new JSONObject();
        //身份类型,必填
        identityObj.put("identity_type", "CERT_INFO");
        //证件类型,必填
        identityObj.put("cert_type", "IDENTITY_CARD");
        //真实姓名,必填
        identityObj.put("cert_name", realName);
        //证件号码,必填
        identityObj.put("cert_no", idNum);

        //构造商户配置json对象
        JSONObject merchantConfigObj = new JSONObject();
        try {
        	//认证完成后手机支付宝的返回页面,我这里返回首页
            String returnUrl = URLEncoder.encode("https://m.alipay.com/Gk8NF23", "UTF-8");
            // 设置回调地址,必填. 如果需要直接在支付宝APP里面打开回调地址使用alipay协议,参考下面的案例:appId用固定值 20000067,url替换为urlEncode后的业务回跳地址
            // alipays://platformapi/startapp?appId=20000067&url=https%3A%2F%2Fapp.cqkqinfo.com%2Fcertify%2FzmxyBackNew.do
            merchantConfigObj.put("return_url", "alipays://platformapi/startapp?appId=20000067&url=" + returnUrl);

            //构造身份认证初始化服务业务参数数据
            JSONObject bizContentObj = new JSONObject();
            //商户请求的唯一标识,推荐为uuid,必填  IdUtil hutool工具
            bizContentObj.put("outer_order_no", IdUtil.simpleUUID());
            bizContentObj.put("biz_code", "FACE");
            bizContentObj.put("identity_param", identityObj);
            bizContentObj.put("merchant_config", merchantConfigObj);
            request.setBizContent(bizContentObj.toString());

            //发起请求
            AlipayUserCertifyOpenInitializeResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                LOGGER.info("[身份验证]初始化身份认证成功:{}", realName);
                //接口调用成功,从返回对象中获取certify_id
                String certifyId = response.getCertifyId();
                // 生成的certifyId 是查询认证结果的凭证,需要保存下来,我这是保存到数据库中,也可保存到redis
                userMapper.insertCertifyId(idNum, certifyId);
                return certifyId;
            } else {
                LOGGER.info("[身份验证]初始化身份认证失败:{}", realName);
                return null;
            }
        } catch (Exception e) {
            LOGGER.error("[身份验证]初始化身份认证失败:{}", realName, e);
            return null;
        }
    }
    
2.生成认证url
	/**
     * 开始认证服务调用
     *
     * @param realName 真实姓名
     * @param idNum    身份证号码
     * @return         url-支付宝认证链接
     */
    public String startCertify(String realName, String idNum) {
        String certifyId = authInitialize(realName, idNum);
        if (StrUtil.isBlank(certifyId)) {
            return null;
        }

        AlipayUserCertifyOpenCertifyRequest request = new AlipayUserCertifyOpenCertifyRequest();
        //设置certifyId
        JSONObject bizContentObj = new JSONObject();
        bizContentObj.put("certify_id", certifyId);
        request.setBizContent(bizContentObj.toString());

        //生成请求链接,这里一定要使用GET模式
        try {
            AlipayUserCertifyOpenCertifyResponse response = alipayClient.pageExecute(request, "GET");
            if (response.isSuccess()) {
                LOGGER.info("[身份验证]开始认证服务调用成功:{}", realName);
                return response.getBody();
            } else {
                LOGGER.info("[身份验证]开始认证服务调用失败:{}", realName);
                return null;
            }
        } catch (AlipayApiException e) {
            LOGGER.error("[身份验证]开始认证服务调用失败:{}", realName, e);
            return null;
        }
    }
    
 3.查询认证结果
 	/**
     * 查询身份认证结果
     *
     * @param certifyId 需要你在你的业务中获取之前保存下来的 certify_id
     * @return
     */
    public boolean queryCertifyResult(String certifyId) {
        AlipayUserCertifyOpenQueryRequest request = new AlipayUserCertifyOpenQueryRequest();
        JSONObject bizContentObj = new JSONObject();
        bizContentObj.put("certify_id", certifyId);
        request.setBizContent(bizContentObj.toString());
        try {
            AlipayUserCertifyOpenQueryResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                LOGGER.info("[身份验证]认证查询服务调用成功:{}", certifyId);
                // 返回的是个json字符串
                String body = response.getBody();
                if (StrUtil.isNotBlank(body)) {
                    JSONObject jsonObject = JSONObject.parseObject(body);
                    // 我们需要获取 alipay_user_certify_open_query_response 下的值
                    JSONObject queryResponse = jsonObject.getJSONObject("alipay_user_certify_open_query_response");
                    LOGGER.info(body); // 你可以打印看一下 json 结构
                    //这里需要注意认证通过的条件 官方文档显示 passed 是个数组,但是它只是一个 String
                    if (StrUtil.equals(queryResponse.getString("code"), "10000") && StrUtil.equals(queryResponse.getString("passed"), "T")) {
                        LOGGER.info("[身份验证]认证通过:{}", certifyId);
                        return true;
                    } else {
                        LOGGER.info("[身份验证]认证失败:{}", certifyId);
                        return false;
                    }
                }
            } else {
                LOGGER.info("[身份验证]认证查询服务调用失败:{}", certifyId);
            }
        } catch (AlipayApiException e) {
            LOGGER.error("[身份验证]开始认证服务调用失败:{}", certifyId, e);
        }
        return false;
    }

这就是调用身份验证的三步。