Files
hfb_sys/docs/顺成汇创交易中心聚合支付/1.交易中心验签示例.md
T

2.5 KiB
Raw Blame History

import json
import hashlib
import base64
from typing import Any, Dict

def build_sign(params: Dict[str, Any], secret_key: str) -> str:
    """
    生成签名
    :param secret_key: 交易密钥
    :return: 计算得到的sign值
    """
    # 1. 剔除值为None的键值对,并处理嵌套对象
    def process_value(value: Any) -> str:
        if isinstance(value, dict):
             # 处理对象:过滤null,排序键
            filtered_obj = {k: v for k, v in value.items() if v is not None}
            # 按键排序
            sorted_keys = sorted(filtered_obj.keys())
            sorted_obj = {k: filtered_obj[k] for k in sorted_keys}
            # 序列化为紧凑JSON
            return  json.dumps(sorted_obj, separators=(',', ':'), ensure_ascii=False)
        elif isinstance(value, (list, tuple)):
            # 列表/元组,直接序列化为紧凑JSON
            return json.dumps(value, separators=(',', ':'), ensure_ascii=False)
        else:
            # 基本类型:字符串、数字、布尔
            return str(value)

    # 对顶层参数进行相同的处理:剔除值=null/空,剔除key="sign",并处理嵌套对象
    filtered_params = {}
    for key, value in params.items():
        if value is None or value == "" or key == "sign":
            continue
        filtered_params[key] = process_value(value)

    # 2. 按键ASCII升序排序
    sorted_keys = sorted(filtered_params.keys())
    # 3. 拼接成 stringAkey1=value1&key2=value2&...
    stringA_parts = []
    for key in sorted_keys:
        value = filtered_params[key]
        # 值如果是字符串,直接使用;否则(理论上不会)转换为字符串
        stringA_parts.append(f"{key}={value}")
    stringA = "&".join(stringA_parts)

    # 4. 追加 &key=密钥
    sign_str = stringA + f"&key={secret_key}"

    # 5. MD5运算
    md5_hash = hashlib.md5(sign_str.encode('utf-8')).digest()
    # 6. 转小写(MD5结果通常是十六进制字符串,这里需要先转十六进制再小写)
    md5_hex = md5_hash.hex().lower()
    # 7. Base64编码
    sign = base64.b64encode(md5_hex.encode('utf-8')).decode('utf-8')
    return sign

# 示例用法
if __name__ == "__main__":
    # 假设请求参数如下
    params = {

    "reqSerialNo": "20260318110810747",
    "data": {
        "merchantId": "******",
        "applyAmount": 10000,
        "reqId": "******",
    }


    }

    secret_key = "******"  # 替换为实际的交易密钥
    sign = build_sign(params, secret_key)
    print(sign)