银联云闪付控件支付--python版本签名、验签代码

说明

  • 接口适用于 所有接入中国银联全渠道平台的商户
  • 商户版银联在线支付网关产品及银联手机支付—银联手机支付—手机控件支付
  • 官方文档如下
    image.png

签名说明

  • 银联需要验证商户上送的签名是否正确;商户收到应答,也需要验证签名是否正确,如果商户未正确验证签名,存在潜在的风险,商户自行承担因此而产生的所有损失。

  • 首先,对报文中出现签名域(signature)之外的所有数据元采用key=value的形式按照名称排序,然后以&作为连接符拼接成待签名串。其次,对待签名串使用SHA-256算法做摘要,再使用银联颁发给商户的签名私钥证书中的私钥对摘要做签名操作(签名时算法选择SHA-256)。最后,对签名做Base64编码,将编码后的签名串放在签名(signature)表单域里和其他表单域一起通过HTTP Post的方式传输给银联全渠道支付平台。

  • 生成签名串方法

    @staticmethod
    def get_sign_data(data: dict):
        """
        获取签名数据
        按照ASCII 字母排序 键值
        {'a':1,'b':2} => 'a=1&b=1'
        @param data:
        @return:
        """
        sort_param = sorted(
            [(key, value) for key, value in data.items() if key not in ['signature']])
        return "&".join("{}={}".format(k, v) for k, v in sort_param)
  • 生成签名的方法
@staticmethod
    def gen_sha1_rsa_sign(sing_data,
                          pri_key):
        """
        银联RSA签名
        :param sing_data:   签名字符串
        :param pri_key:     签名私钥
        :return:
        """
        pri_key = fill_private_key_marker(pri_key)    # 状态 rsa 私钥
        private_key_obj = RSA.import_key(pri_key)
        sign_digest = SHA1.new(sing_data.encode())  # 第一次SHA1计算
        hex_sign_digest = sign_digest.hexdigest()
        sign_digest = SHA1.new(hex_sign_digest.encode())  # 第二次SHA1计算
        signature = pkcs1_15.new(private_key_obj).sign(sign_digest)
        return base64.b64encode(signature).decode('utf-8')

验签说明

  • 对于报文的验签处理机制如下:
  • 首先,对报文中出现签名域(signature)之外的所有数据元采用key=value的形式按照名称排序,然后以&作为连接符拼接成待签名串。其次,对待签名串使用SHA-256算法做摘要,再使用商户入网时银联提供的验签公钥证书中的公钥对摘要和报文中的签名信息做签名验证操作。
@staticmethod
    def verify_rsa_sign(sing_data,
                        sign,
                        pub_key):
        """
            签名验证
        :param sing_data: 签名数据
        :param sign: 签名
        :param pub_key: 公钥
        :return:
        """
        pub_key = fill_public_key_marker(pub_key)
        public_key_obj = RSA.import_key(pub_key)
        sign_digest = SHA1.new(sing_data.encode())
        hex_sign_digest = sign_digest.hexdigest()
        sign_digest = SHA1.new(hex_sign_digest.encode())
        pad_num = 4 - len(sign) % 4
        sign = sign + '=' * pad_num
        try:
            pkcs1_15.new(public_key_obj).verify(sign_digest,
                                                base64.b64decode(sign))
            return True
        except (ValueError, TypeError):
            return False

其他uitils函数

def fill_private_key_marker(private_key):
    return add_start_end(private_key, "-----BEGIN RSA PRIVATE KEY-----\n", "\n-----END RSA PRIVATE KEY-----")


def fill_public_key_marker(public_key):
    return add_start_end(public_key, "-----BEGIN PUBLIC KEY-----\n", "\n-----END PUBLIC KEY-----")


# -----BEGIN RSA PUBLIC KEY-----

def fill_public_key_marker_pem(public_key):
    return add_start_end(public_key, "-----BEGIN RSA PUBLIC KEY-----\n", "\n-----END RSA PUBLIC KEY-----")


@staticmethod
def get_rsa_pri_key_from_pfx(pfx_path, pfx_password):
        """
            获取 xxxxx.pfx 证书的 证书序列号
        :param pfx_path:
        :param pfx_password:
        :return:
        """
        pfx = crypto.load_pkcs12(open(pfx_path, 'rb').read(), bytes(pfx_password, encoding="utf8"))
        _info = pfx.get_certificate()
        serial_number = _info.get_serial_number()
        res = crypto.dump_privatekey(crypto.FILETYPE_PEM, pfx.get_privatekey())
        return serial_number, res.strip()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值