暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

微信支付宝签名逻辑鉴赏

lei子 2021-04-12
1864

        在现今的互联网行业中,一些软件功能开发、流量获取,已经绕不开微信、支付宝等流量入口,特别是在做支付时。 

        本文调研了微信、支付宝的接口请求验证方式,希望对大家对接微信、支付宝的数据签名验证有一些帮助。

微信支付签名验签

一、必须步骤

设置Key密钥,需要商户自行到微信后台中设置。
根据邮件内容下载证书。

二、签名生成算法

  1. 将所有非空参数按照参数名ASCII码从小到大进行排序,包含随机参数:nonce_str,并以&字符进行组合成字符串stringA,即stringA=key1=value1&key2=value2…;

  2. 将key数据附加到stringA字符串之后,以&字符进行连接,得到字符串tempString,即tempString=stringA+&key=**;

  3. 对tempString使用md5算法获取hash值,并将hash值全部转化为大写,得到sign;

  4. 在进行接口请求时必须带上参数:nonce_str、sign。

三、证书方式

微信中,在进行退款、撤销等情形下使用的是证书方式。
证书会在注册商户时,微信官方也邮件方式告知到商户去下载证书。

四、其他相关

项目说明
接口请求方式HTTPS
提交方式POST
数据格式提交、返回数据都使用XML
字符编码UTF-8
签名算法MD5,后续会兼容SHA1、SHA256、HMAC等
签名要求请求和接收数据均需要校验签名,具体签名算法,查看以上部分
证书要求调用申请退款、撤销订单接口需要商户证书
判断逻辑先判断协议字段返回,再判断业务返回,最后判断交易状态

支付宝签名验签

一、必要步骤

利用工具生成RSA密钥,可使用支付宝提供的工具生成公钥、私钥,并保存,建议使用2048位。
将公钥上传至阿里云开放平台中。

二、签名生成算法

  1. 将所有非空参数按照ASCII码从小到大进行排序,需要剔除掉字节类型参数,如文件、字节流等,亦不包含sign字段;

  2. 将所有待签名参数,组合成“key=value”格式,并使用&字符拼接起来,获得字符串stringA;

  3. 利用语言函数SHA256WithRSA(对应sign_type为RSA2)或者SHA1WithRSA(对应sign_type为RSA)签名函数利用商户私钥对待签名字符串(stringA)进行签名,并进行Base64编码;

  4. 将生成的签名赋值给参数:sign,拼接到请求参数中。

PHP中签名函数的需要使用的openSSL扩展。
使用openssl_sign函数进行签名生成。
字符集使用UTF-8。

三、验签过程

  1. 同步返回验签

    1. 从返回数据中获取接口返回参数,如支付宝返回的json中xxx_response的值做验签(xxx代表接口名);

    2. 从上述数据中获取两部分数据:sign、其他数据的json字符串,sign需要进行Base64解码;

    3. 利用语言SHA256WithRSA(对应sign_type为RSA2)或SHA1WithRSA(对应sign_type为RSA)签名验证函数,传入待验签字段、支付宝公钥、签名内容(sign),验签方法(signType)进行验签,根据返回结果判定是否验签通过。

  2. 异步返回验签

    1. 接收所有返回参数,除去sign、sign_type两个参数外,凡是通知返回回来的参数皆是待验签的参数。生活号异步通知组成的待验签串里需要保留sign_type参数。
    2. 将剩下参数进行url_decode, 然后进行字典排序,组成字符串,得到待签名字符串(参考生成签名时算法);
    3. 将签名参数(sign)使用base64解码为字节码串;
    4. 使用RSA的验签方法,通过签名字符串、签名参数(经过base64解码)及支付宝公钥验证签名,根据返回结果判定是否验签通过。
    PHP中验签函数需要使用openssl扩展。
    使用函数openssl_verify函数进行签名验证,签名正确。
    此函数返回1,签名错误返回0,其他错误返回-1

四、其他相关

项目说明
接口请求方式HTTPS
提交方式POST
数据格式JSON
字符编码UTF-8

五、AES加密

支付宝开放平台所有OpenAPI均支持对接口的请求内容和响应内容进行AES加密。
加密后,在网络上传输的接口报文内容将会由明文内容变为密文内容,可以大大提升接口内容传输的安全性。

AES密钥与RSA密钥的关系

AES密钥RSA密钥
对接口请求和响应内容进行加密,密文无法被第三方识别,从而防止接口传输数据泄露接口请求和响应内容进行签名,开发者和支付宝开放平台分别加签验签,以确认接口传输的内容没有被篡改
开发者可对请求参数先做AES加密,然后对密文进行RSA签名
如果开启了支付宝AES加密,开发者需要对返回报文进行先验签,再解密

  1. 请求报文加密

    项目说明
    AES密钥在支付宝页面上生成的AES密钥
    原文biz_content的值
    字符集加密原文会按该字符集转换为对应的编码(请保证和签名过程一致的字符集)
    加密算法AES/CBC/PKCS5Padding
    其它语言基本的加密逻辑一样,需要注意的是对加密后得到字节数组需要先做base64编码,然后再新建字符串 (由于base64后的字节一定是ASCII范围内,所以最后一步new String的时候无需指定字符集)
  2. 响应报文解密

  3. JSON格式

        若存在xml根节点的第一个子节点为response_encrypted,后面紧跟着sign节点,则该报文为加密的报文,密文存放在response_encrypted中

    XML格式

        识别该结
    果是密文的方式是response后的结果是字符串(双引号开头)而不是json对象(大括号开头),密文为引号内的内容



    参考文档:

    [微信接口规则](https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_1)

    [支付宝生成密钥工具](https://docs.open.alipay.com/291/105971/)

    [支付宝签名生成算法介绍](https://docs.open.alipay.com/291/106118)

    [支付宝签名验证算法介绍](https://docs.open.alipay.com/200/106120)

    [支付宝AES加密官方介绍](https://docs.open.alipay.com/common/104567)

文章转载自lei子,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论