python自行实现支付宝证书签名&验签全流程[通俗易懂]

python自行实现支付宝证书签名&验签全流程[通俗易懂]支付宝Pythonsdk只有密钥签名,没有证书签名,下面是本人自行实现签名全流程证书签名需要新加alipay_root_cert_sn和app_cert_sn两个参数,这两个参数需要解析支付宝根证书(alipay_root_cert_sn)和应用公钥证书(appCerPublicKey_”app_id”.crt)得到:defsn_string():root_file_li=open(alipayRootCert.crt’,’r’).read().split(‘\n\n’)

大家好,又见面了,我是你们的朋友全栈君。

在网站使用支付宝python sdk接入支付后成功后,需要实现用户提现功能,在支付宝沙箱环境下使用sdk顺利实现提现,结果转成正式环境后报错,咨询支付宝客服后告知python sdk不支持提现,原因是提现接口需要证书签名,当时就傻眼了,感觉被支付宝沙箱玩弄了,关键是之前写的支付接口也得重写,最后无奈只能舍弃python sdk自行实现签名和验签请求支付宝接口。下面是自行实现签名和验签全流程:

证书签名需要新加alipay_root_cert_sn和app_cert_sn两个参数,这两个参数需要解析支付宝根证书(alipay_root_cert_sn)和应用公钥证书(appCerPublicKey_"app_id".crt)得到:
import OpenSSL
import re
import rsa
import base64	

def sn_string():
    root_file_li = open(alipayRootCert.crt', 'r').read().split('\n\n')
    #  支付宝根证书中有4套证书需要一一解析
    alipay_root_cert_li = []
    for root_str in root_file_li:
        cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, root_str)
        certIssue = cert.get_issuer()
        try:
            if not re.match(b'sha.+WithRSAEncryption', cert.get_signature_algorithm()):
            #  只有符合条件的是需要的,4套证书中只有两个有用(具体为啥咱也不太清楚)
                continue
        except:
            continue
        if certIssue.OU:
            sn_string = 'CN=' + certIssue.CN + ',' + 'OU=' + certIssue.OU + ',' + 'O=' + certIssue.O + ',' + \
                        'C=' + certIssue.C + str(cert.get_serial_number())
                        #  将机构名name和序列号serialNumber按照这样的顺序拼接
        else:
            sn_string = 'CN=' + certIssue.CN + ',' + 'O=' + certIssue.O + ',' + 'C=' + certIssue.C + str(
                         cert.get_serial_number())
        alipay_root_cert_sn = hashlib.md5(sn_string.encode('utf-8')).hexdigest()
        alipay_root_cert_li.append(alipay_root_cert_sn)
    alipay_root_cert_sn = '_'.join(alipay_root_cert_li)
    app_file_str = open(appCertPublicKey_xxxxxxxx.crt', 'r').read()
    app_cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, app_file_str)
    certIssue = app_cert.get_issuer()
    app_sn_string = 'CN=' + certIssue.CN + ',' + 'OU=' + certIssue.OU + ',' + 'O=' + certIssue.O + ',' + \
                    'C=' + certIssue.C + str(app_cert.get_serial_number())
    app_cert_sn = hashlib.md5(app_sn_string.encode('utf-8')).hexdigest()
    return alipay_root_cert_sn, app_cert_sn
得到alipay_root_cert_sn,app_cert_sn后,加到需要请求接口的参数中进行签名;
def alipay_sign(data_dict):

    __pem_begin = '-----BEGIN RSA PRIVATE KEY-----\n'
    __pem_end = '\n-----END RSA PRIVATE KEY-----'

    def rsa_sign(data_dict, private_key_path):
        """SHAWithRSA

        :param content: 签名内容
        :type content: str

        :param private_key: 私钥
        :type private_key: str

        :param _hash: hash算法,如:SHA-1,SHA-256
        :type _hash: str

        :return: 签名内容
        :rtype: str
        """

        private_key = _format_private_key(open(private_key_path, 'r').read())
        pri_key = rsa.PrivateKey.load_pkcs1(private_key.encode('utf-8'))
        params_list = sorted(data_dict.items(), key=lambda e: e[0], reverse=False)  # 参数字典倒排序为列表
        params_str = "&".join(u"{}={}".format(k, v) for k, v in params_list)  # 待签名字符串
        sign_result = rsa.sign(params_str.encode('utf-8'), pri_key, 'SHA-256')
        return base64.b64encode(sign_result)

    def _format_private_key(private_key):
        """对私进行格式化,缺少"-----BEGIN RSA PRIVATE KEY-----"和"-----END RSA PRIVATE KEY-----"部分需要加上

        :param private_key: 私钥
        :return: pem私钥字符串
        :rtype: str
        """
        if not private_key.startswith(__pem_begin):
            private_key = __pem_begin + private_key
        if not private_key.endswith(__pem_end):
            private_key = private_key + __pem_end
        return private_key

    sign = rsa_sign(data_dict, "域名"_私钥.txt')

    return sign
到这里就已经完成了签名这部分,得到签名sign,将其加到请求接口中的参数“sign”中,这里需要注意的是上面得到的alipay_root_cert_sn,app_cert_sn也要加到请求接口中的参数中

支付宝网页支付需要异步验签,异步验签需要用支付宝公钥来验证支付宝传过来的参数和签名。证书签名的情况下支付宝公钥需要解析支付宝公钥证书得到(此处坑太深),下面是实现异步验签流程(这里是在Django下的接口):
def load_alipay_public_key_string():
    alipay_public_key_cert_string = open(alipayCertPublicKey_RSA2.crt').read()
    cert = OpenSSL.crypto.load_certificate(
        OpenSSL.crypto.FILETYPE_PEM, alipay_public_key_cert_string
    )
    public_key = OpenSSL.crypto.dump_publickey(
        OpenSSL.crypto.FILETYPE_PEM, cert.get_pubkey()
    ).decode("utf-8")
    return public_key
def check_alipay(request):
    alipay_req_dict = request.POST.dict()  # 将传过来的支付宝参数转为普通字典
    sign = alipay_req_dict.pop('sign')  # 取出传过来的公钥
    alipay_req_dict.pop('sign_type')  # 去除传过来的sign_type
    params = sorted(alipay_req_dict.items(), key=lambda e: e[0], reverse=False)  # 取出字典元素按key的字母升序排序形成列表
    message = "&".join(u"{}={}".format(k, v) for k, v in params).encode()  # 将列表转为二进制参数字符串
    public_key = load_alipay_public_key_string()
    sign = base64.b64decode(sign)
    status = bool(rsa.verify(message, sign, rsa.PublicKey.load_pkcs1_openssl_pem(public_key)))  # 或者使用sdk下的verify_with_rsa(public_key, message, sign)  # 验签
验签支付宝密钥签名和证书签名都一样,只是证书签名下支付宝公钥需要解析证书得到

这里不得不吐槽下支付宝文档,自行实现签名全给的是参考java sdk实现,网上证书签名和验签文章也没几篇。这里给大家分享下自己实现的全过程,希望能够避免大家少踩点坑。
最后ps:若是支付宝官方觉得我这篇python自行实现支付宝证书签名和验签可以给用户当做参考的话,拿走不谢,哈哈!!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/143892.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 永磁同步电机矢量控制(四)——simulink仿真搭建

    永磁同步电机矢量控制(四)——simulink仿真搭建由于是初学,对于simulink很多地方不熟悉,在此记下整个仿真搭建的选择元件的细节。1电机模型的选择及参数设置永磁同步电机的英文缩写为PMSM,全称PermanentMagnetSynchronousMachine。在library内搜索Permanent即可找到它。Numberofphase电机相数Back…

  • Spring AOP 实现监控方法执行的时间(统计service中方法执行的时间)

    项目中有时候会遇到统计方法执行的时间,来对项目进行优化!下面是我自己在工作中遇到的问题,和我自己的解决方法。要统计出项目中方法执行时间大于1秒的那些方法!我们的项目开发使用的是SpringMVC 那么首先想到使用 Aop Aspet 切面统计,那样子更加方便也高效。1:打开切面!因为项目使用的SpringMVC,项目中的配置文件就配置的 <aop:aspectj-autoproxy …

  • java 三大框架_java的三大框架是什么,功能各是什么

    java 三大框架_java的三大框架是什么,功能各是什么展开全部常说的三大框架指:SSH,即:Spring、62616964757a686964616fe59b9ee7ad9431333365653764Struts、Hibernate。Spring:功能强大的组件粘合济,能够将你的所有的java功能模块用配置文件的方式组合起来成为一个完成的应用。Spring是一个解决了许多在J2EE开发中常见的问题的强大框架。Spring提供了唯一的数据访问抽象,包…

  • java 四舍五入保留小数的几种方式

    java 四舍五入保留小数的几种方式引用处:https://blog.csdn.net/u014704879/article/details/41479399/https://blog.csdn.net/shruber/article/details/78413706https://www.cnblogs.com/Dhouse/p/7776780.html方式一:BigDecimaldoubletpD=6.1…

  • brave浏览器百度百科_世界之窗浏览器下载安装

    brave浏览器百度百科_世界之窗浏览器下载安装给大家安利一个当前世界上最快的新浏览器,Brave狮子王浏览器!如果你经常浏览网页,你一定能体会到打开一个网页比寻常时候快了几秒钟是怎样一种体验,一个优秀的浏览器不仅能为你带来流畅的体验,还能为你节约一定的时间。而且他最爽的一点是超级强力的反tracking,反cookie和反ads。最大化保护隐私! 一直以来我都是chrome浏览器的粉丝,因为chrome的极速还有他…

  • Win11双屏设置双壁纸–2K屏+1080P使用不同壁纸的方法

    Win11双屏设置双壁纸–2K屏+1080P使用不同壁纸的方法先上方法及效果:方法:两张图片(图1尺寸:1920×1080,图2尺寸:2560×1440),Photoshop裁减图1并与图2拼接成一张图片(尺寸:4480×1440)设置为背景图片,并在【个性化-背景】中设置为【平铺】;效果:具体步骤:1.环境:win11(win10类似),屏幕1(1080p),屏幕2(2k屏,16:9);2.所需图片:图1(1920×1080);图2(2560×1440)3.工具:Photoshop(其他拼图工具亦可)4.步骤:1)在PS中【图像-画布大小】中修改画布尺

    2022年10月27日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号