支付加密说明
为了保证交易双方(商户和支付宝)的身份和数据安全,开发者在调用接口前,需要配置双方密钥,对交易数据进行双方校验。密钥包含应用私钥(APP_PRIVATE_KEY)和应用公钥(APP_PUBLIC_KEY)。生成密钥后,开发者需要在开放平台开发者中心进行密钥配置,配置完成后可以获取支付宝公钥(ALIPAY_PUBLIC_KEY)应用在代码中,对请求内容进行签名。支付宝使用RSA非对称加密算法,RSA密钥包括公钥和私钥两部分,公钥是公开信息,私钥是保密信息。在开放平台,开发者的私钥由开发者自己保存;开发者的公钥可对外公开。私钥用于签名,公钥用于验签。开发者保存自己的私钥,并对发给支付宝的信息进行签名,支付宝通过使用开发者的公钥进行验签;(支付宝端类似),通过这种方式保证信息传输的完整性以及发送者身份的真实性。
支付宝签名方式
支付宝提供两种身份验证方式:1.普通公钥验证 2.公钥证书验证。
公钥证书的一个优势在于引入了CA机构对公钥持有者进行身份识别,保证该证书所属实体的真实性,以实现报文的抗抵赖。
- 普通公钥模式生成签名
开放平台 SDK 封装了签名实现,只需在创建 DefaultAlipayClient 对象时,设置请求网关 (gateway),应用 id (app_id),应用私钥 (private_key),编码格式 (charset),支付宝公钥 (alipay_public_key),签名类型 (sign_type)即可,报文请求时会自动进行签名。
AlipayClient alipayClient = new DefaultAlipayClient(gateway,app_id,private_key,"json",charset,alipay_public_key,sign_type);
注意这里我们需要支付宝公钥的目的是:在数据返回时,alipayClient会使用支付宝公钥进行解密,自动验证返回数据的合法性。
- 公钥证书模式生成签名
开放平台 SDK 封装了签名实现,只需在创建 DefaultAlipayClient 对象时,设置请求网关 (gateway),应用 id (app_id),应用私钥 (private_key),应用公钥证书路径(app_cert_path 文件绝对路径),支付宝公钥证书文件路径(alipay_cert_path 文件绝对路径),支付宝CA根证书文件路径(alipay_root_cert_path 文件绝对路径),编码格式 (charset),签名类型 (sign_type)即可,报文请求时会自动进行签名。
CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
certAlipayRequest.setServerUrl(gateway);
certAlipayRequest.setAppId(app_id);
certAlipayRequest.setPrivateKey(privateKey);
certAlipayRequest.setFormat("json");
certAlipayRequest.setCharset(charset);
certAlipayRequest.setSignType(sign_type);
certAlipayRequest.setCertPath(app_cert_path);
certAlipayRequest.setAlipayPublicCertPath(alipay_cert_path);
certAlipayRequest.setRootCertPath(alipay_root_cert_path);
DefaultAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
//发送API请求
AlipayRequest request = new AlipayTradeQueryRequest();
AlipayTradeQueryResponse response = alipayClient.certificateExecute(request);
这里注意:我们导入的证书除开APP公钥证书(app_cert_path)之外,还有两个证书:支付宝公钥证书SN(alipay_cert_sn)与支付宝CA根证书文件路径(alipay_root_cert_path)。这两个证书的作用是:
1.支付宝公钥证书SN(alipay_cert_sn)
开发者上传自己的应用公钥证书后,开放平台会为开发者应用自动签发支付宝公钥证书供开发者下载,用来对开放平台网关响应报文做验签。
但是支付宝公钥证书可能因证书到期或者变更CA签发机构等原因,可能会重新签发证书。在重新签发前,开放平台会在门户上提前提醒开发者支付宝应用公钥证书变更时间。
但为避免开发者因未能及时感知支付宝公钥证书变更而导致验签失败,开放平台提供了一种支付宝公钥证书无感知升级机制,具体流程如下:
1)开放平台网关在响应报文中会多返回支付宝公钥证书SN
2)开放平台网关提供根据SN下载对应支付宝公钥证书的API接口
3)开发者在验签过程中,先比较本地使用的支付宝公钥证书SN与开放平台网关响应中SN是否一致。若不一致,可调用支付宝公钥证书下载接口下载对应SN的支付宝公钥证书。
4)对下载的支付宝公钥证书执行证书链校验,若校验通过,则用该证书验签。
基于该机制可实现支付宝公钥证书变更时开发者无感知,当前开放平台提供的SDK已基于该机制实现对应功能。若开发者未通过SDK接入,须自行实现该功能。
2.支付宝CA根证书文件路径(alipay_root_cert_path)
从上面的问题“使用公钥证书签名模式下,为什么开放平台网关的响应报文需要携带支付宝公钥证书SN”了解到,对动态下载的支付宝公钥证书,我们需要执行证书链校验,在校验过程中,需要使用到支付宝根证书,也就是从开放平台下载的根证书。
但这里有个问题,上面我们提到了支付宝公钥证书变更的原因中,就有可能是因变更根CA(比如根CA到期或者当前的CA机构存在风险)。开放平台变更根CA会提前半年来通知商户及时更新,但不排除有的商户没有及时感知到变更导致变更根CA后,商户验签失败。
为降低该风险,开放平台强制要求使用证书签名模式的商户同时携带当前使用的支付宝根证书SN,开放平台将基于该数据来分析统计未及时更新支付宝根证书的商户。
支付宝回调验证
- 普通公钥模式生成签名
开放平台 SDK 提供了 AlipaySignature.rsaCheckV1 方法,可以使用该方法对通知报文验签。
/**
@param params 参数列表(包括待验签参数和签名值sign) key-参数名称 value-参数值
@param publicKey 验签公钥
@param charset 验签字符集
**/
boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset)
- 公钥证书模式生成签名
开放平台 SDK 提供了 AlipaySignature.rsaCertCheckV1 方法,可以使用该方法对通知报文验签。
/**
@param params 参数列表(包括待验签参数和签名值sign) key-参数名称 value-参数值
@param alipayPublicCertPath 验签支付宝公钥证书路径
@param charset 验签字符集
**/
boolean AlipaySignature.rsaCertCheckV1(Map<String, String> params, String alipayPublicCertPath, String charset)
公钥证书模式注意事项
- 对于之前没有上传过任何公钥,首次接入即使用“公钥证书”的应用,不允许再切换到“公钥”模式。
- 对于从“公钥”变更到“公钥证书”模式的,在变更一周内允许开发者撤销证书回退到“公钥”模式;变更一周后不允许再回退到原模式。开发者调用支付宝网关的代码也需要升级,否则变更一周后原来的“公钥”模式接入会被支付宝网关拦截而无法成功调用,具体升级参考文档。
- 个人开发者因为不涉及到资金类接口,建议使用“公钥”方式进行加签。
- 证书会过期,证书有效期是指证书能够实现其声明功能的期限,证书的功能可包括:签名、加密、身份鉴别。对于签名用途的证书,其私钥只能在证书有效期内才可以用于数字签名,私钥的使用期限不能超过证书的有效期限。但是为了保证在证书有效期内签名的信息可以验证,公钥的使用期限可以在证书的有限期限以外。对于身份鉴别用途的证书,其私钥和公钥只能在证书有效期内才可以使用。另外,证书到期后,在保证安全的情况下,允许使用原密钥对对证书进行更新,但是密钥对不能无限期使用。支付宝开放平台的证书实现的是签名用途,因此,证书有效期过后,其对应的私钥也相应失效,不能再用于签名,公钥验证也不能通过。当用户的证书过期后,接口中使用的证书验证方式将失效,导致openapi调用失败。
数字证书浅析
支付宝推荐开发者使用公钥证书模式的理由是:引入了CA机构对公钥持有者进行身份识别,保证该证书所属实体的真实性,以实现报文的抗抵赖。 下面我们简单了解一下数字证书是什么?
数字证书包含:
- 证书的发布机构 :指出是什么机构发布的这个证书,也就是指明这个证书是哪个公司创建的(只是创建证书,不是指证书的使用者)。对于上面的这个证书来说,就是指"SecureTrust CA"这个机构。
- 证书的有效期 :证书的有效时间,或者说证书的使用期限。 过了有效期限,证书就会作废,不能使用了。
- 公钥 :私钥用于签名,公钥用于验签。
- 证书所有者(Subject):证书是发布给谁的,或者说证书的所有者,一般是某个人或者某个公司名称、机构的名称、公司网站的网址等。
- 签名所使用的算法 : 数字签名所使用的加密算法,这样就可以使用证书发布机构的证书里面的公钥,根据这个算法对指纹进行解密。指纹的加密结果就是数字签名。
- 指纹以及指纹算法 :发布证书时,发布者根据指纹算法(一个hash算法)计算整个证书的hash值(指纹)并和证书放在一起,使用者在打开证书时,自己也根据指纹算法计算一下证书的hash值(指纹),如果和刚开始的值对得上,就说明证书没有被修改过,因为证书的内容被修改后,根据证书的内容计算的出的hash值(指纹)是会变化的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。