如何对XML文件进行gzip压缩?PHP API集成遇签名匹配问题
问题分析与修复方案
1. XML压缩失败的核心原因
simplexml_load_file()返回的是SimpleXMLElement对象,并非XML原始字符串,直接传入gzencode()会因类型不匹配导致压缩失败。你需要读取XML文件的原始文本内容,而非解析成XML对象。
修复代码:
// 直接读取XML文件的原始内容,跳过XML解析步骤 $xml_content = file_get_contents("request.xml") or die("Failed to load"); $gzip = gzencode($xml_content, 9); // 第二个参数指定压缩级别,9为最高压缩率 $base64 = base64_encode($gzip);
2. 签名不匹配(ERROR4000)的问题
你的签名生成逻辑存在两处关键错误:
- 错误地将所有参数拼接后整体执行
urlencode(),正确做法是对每个参数值单独进行urlencode编码,再按API要求的固定顺序拼接键值对 - 签名生成时的字符串拼接规则不符合API要求(通常是
key1=编码后value1key2=编码后value2...的无分隔符格式,需严格遵循参数顺序)
修复签名生成代码:
$username = 'test-app-user'; $req_id = rand(10000000000, 99999999999); $api_token = "za5rth23ku776fdvbn2"; // 对每个参数值单独做urlencode处理 $encoded_command = urlencode($base64); $encoded_req_id = urlencode($req_id); $encoded_username = urlencode($username); // 按API要求的顺序拼接(通常是command、req_id、username的顺序,需确认文档) $string_bazowy = "command=$encoded_command" . "req_id=$encoded_req_id" . "username=$encoded_username"; // 拼接API密钥后生成MD5签名 $string_zmieniony = $string_bazowy . $api_token; $md5 = md5($string_zmieniony);
3. CURL请求的优化建议
若API要求POST参数放在请求体而非URL中,需调整CURL配置:
// 构造POST参数数组 $post_data = [ 'command' => $base64, 'req_id' => $req_id, 'username' => $username, 'req_sig' => $md5 ]; $curl = curl_init(); curl_setopt_array($curl, array( CURLOPT_URL => "https://saldeo-test.brainshare.pl/api/xml/1.0/company/synchronize", CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_MAXREDIRS => 10, CURLOPT_TIMEOUT => 0, CURLOPT_FOLLOWLOCATION => true, CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => http_build_query($post_data), // 自动处理参数的urlencode编码 CURLOPT_HTTPHEADER => array( 'Content-Type: application/x-www-form-urlencoded' ), )); $response = curl_exec($curl); curl_close($curl); echo $response;
额外调试建议
- 打印
$string_bazowy和$string_zmieniony的值,确认格式与API文档要求完全一致 - 用
gzdecode($gzip)验证压缩后的内容能否还原为原始XML,排查压缩环节问题 - 确保
req_id全局唯一,部分API要求每次请求的req_id不能重复
内容的提问来源于stack exchange,提问作者Konrad
相关产品推荐
相关产品推荐

