长时间没有使用支付宝的支付接口,再次实用的发现现在验签方式只剩ras2了。比较蛋疼的一点在于自己怎么处理都处理不对,于是使用支付宝的签名工具进行验签发现依然验证失败。
代码根据支付宝的相关文档进行了处理,但是依然失败。直到搜索到了这篇文章https://bbs.csdn.net/topics/392301160?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task,里面提到可能是签名工具版本的问题:
支付宝提供了RSA的验签生成工具,之前我使用的是1.0版的,生成的密钥可以支持支付,但是在回调的时候会校验失败,后面重新下载了1.3版的,就好了
但是比较蛋疼的是从支付宝的官方文档中并没有找到这个文件的下载地址,一通搜索最后才找到这个工具:http://p.tb.cn/rmsportal_6680_secret_key_tools_RSA_win.zip?spm=a2c4e.10696291.0.0.110e19a4SEQto8&file=rmsportal_6680_secret_key_tools_RSA_win.zip
下载之后发现通过这个工具是可以验签成功的。这个就尼玛奇怪了,简直神坑。如果使用这个工具依然没有办法验签可以尝试以下操作
- 对于响应报文进行urldecode
- 使用该工具重新生成秘钥,替换掉app正在使用的秘钥。
签名过程可以通过日志类查看:
一、验签准备
1.原始报文:
【gmt_create=2020-03-25 10:59:32&charset=utf-8&gmt_payment=2020-03-25 10:59:38¬ify_time=2020-03-25 10:59:38&subject=仙玉小袋&sign=zs+snU7B3l4Cnec/JWBcXWkFUNWrW1ttEeMZI4X2mtuSNQ9LL9Mri3b6QK0xTc/KMs/Cafk0Ln7iRKQZfnuBvvuaOwVxSgjuWT0ygGktDok0HITE2wKeT8j4SNX4ScIGHLqHXkMojXIZxE6bsfD9kjUb356aFItinf3vURu3FuPSkbJR1KZXDm41hz2rQ9o6Sc3Xs2cr7AbCSVgyGjv5c6G6OiqaXcdgM+FxHtxkhfqB/3awRjXMGmLmWr2m5VyFIfNMOuNCdRN7fNkUBIX3h35KI6av/x6BDYKwTW2zrJHVy91C0h3mrVoDNuRrJ4fPMW2ZH88j7Q3exmPTP0gqMA==&buyer_id=2088002582656381&body=仙玉小袋&invoice_amount=0.01&version=1.0¬ify_id=2020032500222105938056380529774436&fund_bill_list=[{"amount":"0.01","fundChannel":"PCREDIT"}]¬ify_type=trade_status_sync&out_trade_no=TEST171&total_amount=0.01&trade_status=TRADE_SUCCESS&trade_no=2020032522001456380542497258&auth_app_id=2021001144680325&receipt_amount=0.01&point_amount=0.00&buyer_pay_amount=0.01&app_id=2021001144680325&sign_type=RSA2&seller_id=2088031940831575】
2.验签公钥:
【MIIBIjANBgktf9owIDAQAB】
3.从报文取出签名值sign:
【zs+snU7B3l4Cnec/JWBcXWkFUNWrW1ttEeMZI4X2mtuSNQ9LL9Mri3b6QK0xTc/KMs/Cafk0Ln7iRKQZfnuBvvuaOwVxSgjuWT0ygGktDok0HITE2wKeT8j4SNX4ScIGHLqHXkMojXIZxE6bsfD9kjUb356aFItinf3vURu3FuPSkbJR1KZXDm41hz2rQ9o6Sc3Xs2cr7AbCSVgyGjv5c6G6OiqaXcdgM+FxHtxkhfqB/3awRjXMGmLmWr2m5VyFIfNMOuNCdRN7fNkUBIX3h35KI6av/x6BDYKwTW2zrJHVy91C0h3mrVoDNuRrJ4fPMW2ZH88j7Q3exmPTP0gqMA==】
二、组成待验签串:
1.剔除空值参数:
【gmt_create=2020-03-25 10:59:32&charset=utf-8&gmt_payment=2020-03-25 10:59:38¬ify_time=2020-03-25 10:59:38&subject=仙玉小袋&sign=zs+snU7B3l4Cnec/JWBcXWkFUNWrW1ttEeMZI4X2mtuSNQ9LL9Mri3b6QK0xTc/KMs/Cafk0Ln7iRKQZfnuBvvuaOwVxSgjuWT0ygGktDok0HITE2wKeT8j4SNX4ScIGHLqHXkMojXIZxE6bsfD9kjUb356aFItinf3vURu3FuPSkbJR1KZXDm41hz2rQ9o6Sc3Xs2cr7AbCSVgyGjv5c6G6OiqaXcdgM+FxHtxkhfqB/3awRjXMGmLmWr2m5VyFIfNMOuNCdRN7fNkUBIX3h35KI6av/x6BDYKwTW2zrJHVy91C0h3mrVoDNuRrJ4fPMW2ZH88j7Q3exmPTP0gqMA==&buyer_id=2088002582656381&body=仙玉小袋&invoice_amount=0.01&version=1.0¬ify_id=2020032500222105938056380529774436&fund_bill_list=[{"amount":"0.01","fundChannel":"PCREDIT"}]¬ify_type=trade_status_sync&out_trade_no=TEST171&total_amount=0.01&trade_status=TRADE_SUCCESS&trade_no=2020032522001456380542497258&auth_app_id=2021001144680325&receipt_amount=0.01&point_amount=0.00&buyer_pay_amount=0.01&app_id=2021001144680325&sign_type=RSA2&seller_id=2088031940831575】
2.剔除sign、sign_type参数:
【gmt_create=2020-03-25 10:59:32&charset=utf-8&gmt_payment=2020-03-25 10:59:38¬ify_time=2020-03-25 10:59:38&subject=仙玉小袋&buyer_id=2088002582656381&body=仙玉小袋&invoice_amount=0.01&version=1.0¬ify_id=2020032500222105938056380529774436&fund_bill_list=[{"amount":"0.01","fundChannel":"PCREDIT"}]¬ify_type=trade_status_sync&out_trade_no=TEST171&total_amount=0.01&trade_status=TRADE_SUCCESS&trade_no=2020032522001456380542497258&auth_app_id=2021001144680325&receipt_amount=0.01&point_amount=0.00&buyer_pay_amount=0.01&app_id=2021001144680325&seller_id=2088031940831575】
3、排序:
【app_id=2021001144680325&auth_app_id=2021001144680325&body=仙玉小袋&buyer_id=2088002582656381&buyer_pay_amount=0.01&charset=utf-8&fund_bill_list=[{"amount":"0.01","fundChannel":"PCREDIT"}]&gmt_create=2020-03-25 10:59:32&gmt_payment=2020-03-25 10:59:38&invoice_amount=0.01¬ify_id=2020032500222105938056380529774436¬ify_time=2020-03-25 10:59:38¬ify_type=trade_status_sync&out_trade_no=TEST171&point_amount=0.00&receipt_amount=0.01&seller_id=2088031940831575&subject=仙玉小袋&total_amount=0.01&trade_no=2020032522001456380542497258&trade_status=TRADE_SUCCESS&version=1.0】
三、验签结果:
【验签成功】
不过有一点还需要注意,那就是python的urllib.parse.unquote(v)处理之后还要进行进一步的处理,将时间中的“+”替换为“ ”(空格),不然依然无法通过校验:
sign = b'zs+snU7B3l4Cnec/JWBcXWkFUNWrW1ttEeMZI4X2mtuSNQ9LL9Mri3b6QK0xTc/KMs/Cafk0Ln7iRKQZfnuBvvuaOwVxSgjuWT0ygGktDok0HITE2wKeT8j4SNX4ScIGHLqHXkMojXIZxE6bsfD9kjUb356aFItinf3vURu3FuPSkbJR1KZXDm41hz2rQ9o6Sc3Xs2cr7AbCSVgyGjv5c6G6OiqaXcdgM+FxHtxkhfqB/3awRjXMGmLmWr2m5VyFIfNMOuNCdRN7fNkUBIX3h35KI6av/x6BDYKwTW2zrJHVy91C0h3mrVoDNuRrJ4fPMW2ZH88j7Q3exmPTP0gqMA=='
plaintext = app_id=2021001144680325&auth_app_id=2021001144680325&body=仙玉小袋&buyer_id=2088002582656381&buyer_pay_amount=0.01&charset=utf-8&fund_bill_list=[{"amount":"0.01","fundChannel":"PCREDIT"}]&gmt_create=2020-03-25 10:59:32&gmt_payment=2020-03-25 10:59:38&invoice_amount=0.01¬ify_id=2020032500222105938056380529774436¬ify_time=2020-03-25 10:59:38¬ify_type=trade_status_sync&out_trade_no=TEST171&point_amount=0.00&receipt_amount=0.01&seller_id=2088031940831575&subject=仙玉小袋&total_amount=0.01&trade_no=2020032522001456380542497258&trade_status=TRADE_SUCCESS&version=1.0
hash_value =
True
sign = b'zs+snU7B3l4Cnec/JWBcXWkFUNWrW1ttEeMZI4X2mtuSNQ9LL9Mri3b6QK0xTc/KMs/Cafk0Ln7iRKQZfnuBvvuaOwVxSgjuWT0ygGktDok0HITE2wKeT8j4SNX4ScIGHLqHXkMojXIZxE6bsfD9kjUb356aFItinf3vURu3FuPSkbJR1KZXDm41hz2rQ9o6Sc3Xs2cr7AbCSVgyGjv5c6G6OiqaXcdgM+FxHtxkhfqB/3awRjXMGmLmWr2m5VyFIfNMOuNCdRN7fNkUBIX3h35KI6av/x6BDYKwTW2zrJHVy91C0h3mrVoDNuRrJ4fPMW2ZH88j7Q3exmPTP0gqMA=='
plaintext = app_id=2021001144680325&auth_app_id=2021001144680325&body=仙玉小袋&buyer_id=2088002582656381&buyer_pay_amount=0.01&charset=utf-8&fund_bill_list=[{"amount":"0.01","fundChannel":"PCREDIT"}]&gmt_create=2020-03-25+10:59:32&gmt_payment=2020-03-25+10:59:38&invoice_amount=0.01¬ify_id=2020032500222105938056380529774436¬ify_time=2020-03-25+10:59:38¬ify_type=trade_status_sync&out_trade_no=TEST171&point_amount=0.00&receipt_amount=0.01&seller_id=2088031940831575&subject=仙玉小袋&total_amount=0.01&trade_no=2020032522001456380542497258&trade_status=TRADE_SUCCESS&version=1.0
hash_value =
False
签名校验可以使用下面的代码(针对rsa2):
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5
import Crypto.Hash.SHA512
from Crypto.Hash import SHA, SHA256
import base64
def rsa2_verify(sign, plaintext, keypath):
print('*' * 100)
print('sign =', sign)
with open(keypath) as f:
key = f.read()
print('plaintext =', plaintext)
hash_value = SHA256.new(plaintext.encode('utf-8'))
print('hash_value =', hash_value)
verifier = PKCS1_v1_5.new(RSA.importKey(key))
# 验证,通过返回true,失败返回false
print('*' * 100)
return verifier.verify(hash_value, base64.b64decode(sign))
if __name__ == '__main__':
message = 'app_id=2021001144680325&auth_app_id=2021001144680325&trade_status=TRADE_SUCCESS&version=1.0'
publickeyPath = r"H:\alipay\xn\alipay_public.txt" # alipay的公钥 不是app公钥
result = rsa2_verify(signature, message, publickeyPath)
print('result =', result)