建行B2B支付回调参数乱码现象解析(转)

本文介绍了解决建行B2B支付系统与ASP.NET系统因编码不同导致的回调参数乱码问题。通过直接读取原始字节流并使用正确的编码(GBK)进行解析,实现了正确获取和处理中文参数。

建行B2B支付采用Java开发,页面回调采用POST提交方式,编码为GBK。而我们的系统为ASP.NET,编码UTF-8。通过Request获取的参数是乱码,无奈之下,只能从InputStream解析。解析代码如下:
       

log.Debug("Request Absolute Uri:" + this.Request.Url.AbsoluteUri);
            
            //GBK解析
            BinaryReader reader = new BinaryReader(this.Request.InputStream);
            Byte[] bs = reader.ReadBytes((int)this.Request.InputStream.Length);
            String parameter = HttpUtility.UrlDecode(Encoding.GetEncoding("ISO-8859-1").GetString(bs), Encoding.GetEncoding("GBK"));

            NameValueCollection parameterDic = HttpUtility.ParseQueryString(parameter);
            if (parameterDic != null && parameterDic.Count > 0)
            {
                foreach (String key in parameterDic.Keys)
                {
                    log.Debug("Query Param Key:" + key + " Value:" + parameterDic[key]);
                }
            }



服务端通知采用的GET方式,更郁闷的时,建行竟然对中文参数不做UrlEncode操作,直接用GBK编码回调过来,害得我们浪费了很长时间,还是从最原始的字节码出发,代码如下:
          

log.Debug("Request Absolute Uri:" + this.Request.Url.AbsoluteUri);
            
            IServiceProvider provider = (IServiceProvider)HttpContext.Current;
            HttpWorkerRequest worker = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
            byte[] bs = worker.GetQueryStringRawBytes();
            String queryString = Encoding.GetEncoding("GBK").GetString(bs);
            log.Debug("Query String:" + queryString);

            NameValueCollection querys = HttpUtility.ParseQueryString(queryString);
            if (querys != null && querys.Count > 0)
            {
                foreach (String key in querys.AllKeys)
                {
                   log.Debug("Query Param Key:" + key + " Value:" + querys[key]);
                }
            }


 

### 建设银行聚合支付回调中的数字签名实现 在处理建设银行聚合支付回调请求时,确保数据完整性和真实性至关重要。通常情况下,这类系统会采用哈希函数配合非对称加密的方式来进行数字签名验证。 #### 1. 数字签名流程概述 当商户接收到由建设银行发送过来的通知消息时,该通知包含了业务参数以及一个名为`sign`字段的数字签名值。为了确认这条信息确实来自建设银行并且未被篡改,在解析并提取出所有参与签名的数据项之后,需要按照特定顺序拼接这些字符串,并通过相同的摘要算法重新计算一次散列值。最后比较新生成的结果与原始`sign`值是否一致来完成校验过程[^1]。 #### 2. 签名算法细节 对于具体的签名算法而言,常见的做法如下: - **输入参数**:选取所有用于构建签名串的关键参数(排除某些特殊字符),并将它们按ASCII码升序排列; - **连接符**:使用固定的分隔符(如&)将上述整理后的键值对相连成完整的待签字符串; - **密钥加入**:在最终形成的字符串前后附加双方事先约定好的私有密钥作为额外的安全层; - **Hash运算**:选用MD5或SHA系列等强健的一向性哈希函数对该组合体执行单次不可逆变换操作得到固定长度的消息摘要; - **编码换**:有时还需要进一步利用Base64或其他机制把二进制形式为可读性强的文字表达以便传输存储。 ```python import hashlib from urllib.parse import quote_plus def generate_sign(params, secret_key): """ Generate the sign string based on given parameters and secret key. Args: params (dict): Dictionary containing all necessary fields for signing. secret_key (str): Secret key shared between both parties. Returns: str: Generated signature value after applying hash function. """ # Step 1: Sort keys alphabetically and filter out empty values sorted_items = [(k, v) for k, v in sorted(params.items()) if v] # Step 2: Create query string with URL encoding encoded_query_string = "&".join(f"{quote_plus(k)}={quote_plus(str(v))}" for k, v in sorted_items) # Step 3: Concatenate pre-shared secret at beginning and end of message body raw_data_to_hash = f"{secret_key}{encoded_query_string}{secret_key}" # Step 4: Apply SHA-256 hashing algorithm to produce final digest sha_256 = hashlib.sha256() sha_256.update(raw_data_to_hash.encode('utf-8')) hashed_result = sha_256.hexdigest().upper() return hashed_result ``` 此代码片段展示了如何根据给定的参数集和共享秘密创建一个符合标准的数字签名。请注意实际应用中可能涉及到更多复杂的逻辑调整以适应具体API的要求[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值