zoukankan      html  css  js  c++  java
  • 微信支付v3版几个重难点(签名、验签、加密、解密)的python实现

    背景介绍

    v3版微信支付通过商户证书和平台证书加强了安全性,也大幅提高了开发难度,python版sdk包wechatpayv3内部封装了安全性相关的签名、验签、加密和解密工作,降低了开发难度。下面几个特性的实现,更方便了开发者。

    1. 平台证书自动更新,无需开发者关注平台证书有效性,无需手动下载更新;
    2. 支持本地缓存平台证书,初始化时指定平台证书保存目录即可。
    3. 敏感信息直接传入明文参数,SDK内部自动加密,无需手动处理。

    在这里将sdk内部几个涉及到安全性的方法单独抽出来结合官方文档对照一下,方便大家更直观的理解,有兴趣探究sdk内部实现细节的同学可以了解一下,一般应用的无需关注,直接调用sdk包即可。

    构造签名信息

    对应v3版微信支付api文档的签名生成部分。

    def build_authorization(path,
                            method,
                            mchid,
                            serial_no,
                            mch_private_key,
                            data=None,
                            nonce_str=None):
        timeStamp = str(int(time.time()))
        nonce_str = nonce_str or ''.join(str(uuid.uuid4()).split('-')).upper()
        body = json.dumps(data) if data else ''
        sign_str = '%s
    %s
    %s
    %s
    %s
    ' % (method, path, timeStamp, nonce_str, body)
        signature = rsa_sign(private_key=mch_private_key, sign_str=sign_str)
        authorization = 'WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",signature="%s",timestamp="%s",serial_no="%s"' % (mchid, nonce_str, signature, timeStamp, serial_no)
        return authorization
    

    验证签名

    对应v3版微信支付api文档的签名验证部分。

    def rsa_verify(timestamp, nonce, body, signature, certificate):
        sign_str = '%s
    %s
    %s
    ' % (timestamp, nonce, body)
        public_key = certificate.public_key()
        message = sign_str.encode('UTF-8')
        signature = b64decode(signature)
        try:
            public_key.verify(signature, sign_str.encode('UTF-8'), PKCS1v15(), SHA256())
        except InvalidSignature:
            return False
        return True
    

    回调信息解密

    对应v3版微信支付api文档的证书和回调报文解密部分。

    def aes_decrypt(nonce, ciphertext, associated_data, apiv3_key):
        key_bytes = apiv3_key.encode('UTF-8')
        nonce_bytes = nonce.encode('UTF-8')
        associated_data_bytes = associated_data.encode('UTF-8')
        data = b64decode(ciphertext)
        aesgcm = AESGCM(key=key_bytes)
        try:
            result = aesgcm.decrypt(nonce=nonce_bytes, data=data, associated_data=associated_data_bytes).decode('UTF-8')
        except InvalidTag:
            result = None
        return result
    

    敏感信息加密

    对应v3版微信支付api文档的敏感信息加解密的加密部分。

    def rsa_encrypt(text, certificate):
        data = text.encode('UTF-8')
        public_key = certificate.public_key()
        cipherbyte = public_key.encrypt(
            plaintext=data,
            padding=OAEP(mgf=MGF1(algorithm=SHA1()), algorithm=SHA1(), label=None)
        )
        return b64encode(cipherbyte).decode('UTF-8')
    

    敏感信息解密

    对应v3版微信支付api文档的敏感信息加解密的解密部分。

    def rsa_decrypt(ciphertext, private_key):
        data = private_key.decrypt(ciphertext=b64decode(ciphertext), padding=OAEP(mgf=MGF1(algorithm=SHA1), algorithm=SHA1))
        result = data.decode('UTF-8')
        return result
    

    注意事项

    以上涉及到的几项签名如果计划抽出来单独使用,需要引入cryptography包。

  • 相关阅读:
    挖地雷——线性dp
    hdu6376 度度熊剪纸条-----01背包
    Problem
    UVa 10635
    Vjudge_题目分享_A -> 线性Dp排列木棍 ( Dilworth定理应用
    洛谷日报 & 原来博客(转载)
    使用.net6 WebApplication打造最小API
    k8s笔记——NodePort暴露nginx-controller实现https自动跳转自定义nodePort端口
    通过Dapr实现一个简单的基于.net的微服务电商系统(十七)——服务保护之动态配置与热重载
    通过Dapr实现一个简单的基于.net的微服务电商系统(十六)——dapr+sentinel中间件实现服务保护
  • 原文地址:https://www.cnblogs.com/minibear2000/p/15252174.html
Copyright © 2011-2022 走看看