支付宝口碑isv开发如何正确处理签名
简单的知识点
- 本文基本分初级、进阶、高级三部
- 初级适用群体:使用 demo 或 SDK 开发系统,对 RSA 签名规则
不熟悉
的同学 - 进阶适用群体:使用 SDK 开发系统,对 RSA 签名规则
熟悉
的同学 - 仅使用SDK需要对开放平台签名规则略有了解。
- 适合遇到网关返回报文中描述
签名错误
。 - 高级适用群体: 不使用 demo或 SDK、完全独立开发。对RSA 签名规则
熟悉
的同学 - 注:推荐使用 SDK。否则请直接跳高级说明。
- 初级适用群体:使用 demo 或 SDK 开发系统,对 RSA 签名规则
- 推荐使用 demo 或者 SDK。可以节约开发同学学习RSA签名规则的时间。
- 初次对接开放平台接口时建议选择参数较少的简单接口对接,方便调查问题。
- 支付宝产品分 mapi 网关产品及 openapi 网关产品。
- mapi 网关均使用支付宝PID调用,需配置合作伙伴秘钥。
- 因 mapi 多使用 md5验签,问题较少,因此本文仅介绍开放平台签名规则。
- openapi 网关产品均使用支付宝 appid 调用,需在appid上分别配置秘钥。
- 如有多个 appid, 使用相同秘钥或者不同秘钥均可,只需保证自己调用时使用配对秘钥加签即可。
初级教程
对于新接入支付宝产品的开发,如何生成密钥、开放平台设置密钥 很重要
- 获取 PID
?点击查看
- 详解如何查询 支付宝账号PID.
- RSA秘钥生成
?点击查看
- 推荐使用在线地址中生成工具,该工具同样可做秘钥校验作用.(问题排查工具)
- 上传公钥
?点击查看
- 在此页面可以上传商户公钥及查看支付宝公钥(支付宝公钥唯一,因此代码中不做修改最好,以免节外生枝.)
- demo&sdk使用方法
?点击查看
- 参考文中的配置方法将第二步中生成的私钥填写.
- 注意最新
.net
demo 对aop.DefaultAopClient方法做了改善,添加了两个参数.最后一个参数keyFromFile
.- 为true时直接写私钥本地路径.
- 默认 false, 需要将私钥内容转成一行填入方法中.
进阶教程
进阶教程主要针对在使用时碰到签名错误的同学
- 一般平台返回签名错误 个人建议按照初级教程仔细核对一遍.
- 可能原因1:账号多人使用,被其他同事或者其他公司员工修改
- 建议跟商户相关负责人沟通,看谁有可能修改秘钥,因为修改秘钥需要短信验证码,所以肯定能查出问题根源.
- 绑定手机号应该是公司相对高层人士,与其沟通不要随便将短信码给其他人.
- 可能原因2:自己误操作导致公钥不匹配
- 在开放平台有多个应用,上传公钥时需上传系统使用 appid 相同应用的商户公钥.
- 生成了多套秘钥或者其他原因导致程序里私钥与平台设置的公钥不匹配
- 该问题建议使用
初级教程
:[RSA秘钥生成]
中的工具做排查,校验公私钥是否匹配. - 如不匹配可使用私钥重新生成公钥配置到开放平台.
- 或者重新生成一套按
初级教程
:上传公钥
重新配置 - 可能原因3:如果调用api中传参包含中文,则很有可能是因为编码问题导致开放平台验签失败.
- 调查方法,将参数中所有中文替换成英文重试接口调用,如果成功说明是编码影响平台验签.
- 修改方法,参考
初级教程
:demo&sdk使用方法
在DefaultAopClient方法中传入相应编码集. - 下面介绍出现这个问题的原因,感兴趣的同学可以看下.
- 中文包含多种编码集,而你们系统有默认编码集,当你参数中含有中文且在调用签名方法时没有指明编码集,系统会使用默认编码集进行签名.而调用接口时需传入
charset
参数, 如果你没传入,平台会使用默认编码集utf-8
解签,如果你系统默认utf-8
编码,那么此问题你无感知,但如果是非utf-8
类型编码会导致平台算签名串与你实际传入不符. 最终验签失败
- 系统直接报错,抛出的异常建议自己先分析.
- 常见的异常就是获取私钥失败.可能的原因如下(低级错误请仔细排查)
- 使用java开发但是私钥未经过
pkcs8
转码 - 使用.net开发,参考
初级教程
:demo&sdk使用方法
,未对keyFromFile
做有效控制. - 复制私钥没复制全.
- 使用java开发但是私钥未经过
- 其他异常均属于代码错误,建议先自己排查.实在搞不定可以联系
技术支持
协助解决.
- 常见的异常就是获取私钥失败.可能的原因如下(低级错误请仔细排查)
高级教程
高级教程针对不使用 SDK开发的同学(安全考虑/冷门语言等原因)
- 高级教程需要你首先了解初级教程,并且进阶教程中的常见问题也可以自己排查解决.
- 本文主要探讨开放平台签名规则,如不使用sdk开发,这些逻辑代码均需要自己开发.
- 建议开发前先参考 sdk 源代码看下实际处理
- 签名机制
?点击查看
mapi
网关产品签名时要去掉sign_type=RSA
,这点跟openapi
网关产品不同,一定要注意.- 排序时不要仅排序第一个字符,要注意第一字符相同时排第二字符,以此类推.
- 所有
空参数
不在签名参数中,注意剔除.异步通知(需要解签报文)同理 - 支付宝异步通知不会有
空参数
PHP下SSL加密解密、验证、签名方法(很简单)
RSA超级简单,依赖于OpenSSL扩展,这里就不多废话了,直接奉上代码
签名:
function sign($data) {
//读取私钥文件(签名一定是商户自己本地生成的私钥)
$priKey = file_get_contents('key/rsa_private_key.pem');
//转换为openssl密钥,必须是没有经过pkcs8转换的私钥(不要使用这个私钥rsa_private_key_pkcs8.pem)
$res = openssl_get_privatekey($priKey);
//调用openssl内置签名方法,生成签名$sign
openssl_sign($data, $sign, $res);
//释放资源
openssl_free_key($res);
return $sign;
}
验证:
function verify($data, $sign) {
//读取支付宝公钥文件(一定是阿里后台生成提供的公钥)
$pubKey = file_get_contents('key/alipay_public_key.pem');
//转换为openssl格式密钥
$res = openssl_get_publickey($pubKey);
//调用openssl内置方法验签,返回bool值
$result = (bool)openssl_verify($data, $sign, $res);
//释放资源
openssl_free_key($res);
return $result;
解密
function decrypt($content) {
//读取商户私钥(商户自己生成的私钥)
$priKey = file_get_contents('key/rsa_private_key.pem');
//转换为openssl密钥,必须是没有经过pkcs8转换的私钥
$res = openssl_get_privatekey($priKey);
//声明明文字符串变量
$result = '';
//循环按照128位解密
for($i = 0; $i < strlen($content)/128; $i++ ) {
$data = substr($content, $i * 128, 128);
//拆分开长度为128的字符串片段通过私钥进行解密,返回$decrypt解析后的明文
openssl_private_decrypt($data, $decrypt, $res);
//明文片段拼接
$result .= $decrypt;
}
//释放资源
openssl_free_key($res);
//返回明文
return $result;
}
AES密钥是什么
高级加密标准(英语:Advanced Encryption Standard,缩写:AES),是目前对称密钥加密中比较通用的一种加密方式。
AES密钥有什么用
支付宝开放平台所有OpenAPI均支持对接口的请求内容和响应内容进行AES加密,部分OpenAPI(芝麻信用等)强制要求AES加密。加密后,在网络上传输的接口报文内容将会由明文内容变为密文内容,可以大大提升接口内容传输的安全性。
AES密钥与RSA密钥的关系
- AES密钥是对接口请求和响应内容进行加密,密文无法被第三方识别,从而防止接口传输数据泄露。
- RSA密钥是对接口请求和响应内容进行签名,开发者和支付宝开放平台分别加签验签,以确认接口传输的内容没有被篡改。不论接口内容是明文还是密文,RSA均可正常签名。
- 开发者可对请求参数先做AES加密,然后对密文进行RSA签名。