```python 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. 拼接成 stringA:key1=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) ```