Java支付宝身份验证接口接入指南
最近公司项目有人脸身份核验的需求,首先就想到了支付宝的身份验证接口,于是就需要看支付宝的开放api文档,这里就有些坑,然后就本次接入遇到的坑,做个整理。(基于web网页)
一.文档查找
我们要用的接口就图中的三个:
但是不推荐看上图中的api文档,不知什么原因,这三个接口的传参及返回值有些混乱,导致无法顺利接入。
推荐看这个地址的文档:https://docs.open.alipay.com/20181012100420932508
或者看我现在写的这篇(根据上面的这个文档整理的)。
二.前期准备
首先确保你有一个企业支付宝账号,身份验证需要签约商户,要企业支付宝开发者才能调用。将你手中的企业支付宝入驻到支付宝开放平台。
1.创建应用
要在您的应用中接入身份验证能力,您需要登录 开放平台控制台,在控制台创建您的应用,应用审核通过后会生成应用唯一标识(APPID),并且可以申请开通开放产品使用权限。通过 APPID 您的应用才能调用开放产品的接口能力。需要详细了解开放平台创建应用步骤请参见 创建应用。
2.配置应用
添加能力
应用创建完成后,系统会自动跳转到应用详情页面。开发者可以点击 添加能力 选择 身份验证 来添加能力。
这里需要说明一下:身份验证能力添加好了后,需要关联,点击商家中心,关联你的应用。
配置密钥
为了保证交易双方(商户和支付宝)的身份和数据安全,开发者在调用接口前,需要配置双方密钥,对交易数据进行双方校验。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;
}
这就是调用身份验证的三步。