首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 接收與發送 XML 數據:cURL 與 fsockopen 實戰

     編輯:PHP 相關知識

接收 XML(HTTP 原始輸入流)

<?php
// 僅讀取原始 POST 數據(Content-Type: text/xml 或 application/xml)
$xmlString = file_get_contents('php://input');

if (empty($xmlString)) {
    http_response_code(400);
    exit('Empty XML body');
}

// 解析 XML
libxml_use_internal_errors(true);
$xml = simplexml_load_string($xmlString);
if ($xml === false) {
    $errors = libxml_get_errors();
    libxml_clear_errors();
    http_response_code(400);
    exit('Invalid XML: ' . $errors[0]->message);
}

// 業務處理...
$response = ['status' => 'ok', 'received' => (string)$xml->getName()];
header('Content-Type: application/json');
echo json_encode($response);
?>

發送 XML(cURL 推薦)

<?php
function postXml(string $url, string $xmlData, array $options = []): string|false {
    $ch = curl_init($url);

    $defaultOptions = [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $xmlData,
        CURLOPT_HTTPHEADER => [
            'Content-Type: application/xml; charset=utf-8',
            'Content-Length: ' . strlen($xmlData)
        ],
        CURLOPT_TIMEOUT => 30,
        CURLOPT_CONNECTTIMEOUT => 10,
        CURLOPT_SSL_VERIFYPEER => true,  // 生產必開
        CURLOPT_SSL_VERIFYHOST => 2,
    ];

    curl_setopt_array($ch, $defaultOptions + $options);

    $response = curl_exec($ch);
    $errNo = curl_errno($ch);
    $errMsg = curl_error($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($errNo) {
        error_log("cURL error ($errNo): $errMsg for $url");
        return false;
    }
    if ($httpCode >= 400) {
        error_log("HTTP $httpCode from $url: $response");
    }
    return $response;
}

// 使用
$xml = '12399.9';
$result = postXml('https://api.example.com/orders', $xml);
?>

發送 XML(fsockopen 底層 Socket,無 cURL 環境)

<?php
function postXmlSocket(string $host, string $path, string $xmlData, int $port = 443, bool $ssl = true): string|false {
    $scheme = $ssl ? 'ssl://' : '';
    $fp = fsockopen($scheme . $host, $port, $errNo, $errStr, 10);
    if (!$fp) {
        error_log("Socket connect failed ($errNo): $errStr");
        return false;
    }

    $request = "POST $path HTTP/1.1\r\n";
    $request .= "Host: $host\r\n";
    $request .= "Content-Type: application/xml; charset=utf-8\r\n";
    $request .= "Content-Length: " . strlen($xmlData) . "\r\n";
    $request .= "Connection: close\r\n";
    $request .= "\r\n";
    $request .= $xmlData;

    fwrite($fp, $request);

    $response = '';
    while (!feof($fp)) {
        $response .= fgets($fp, 4096);
    }
    fclose($fp);

    // 簡易分離 Header/Body
    list($header, $body) = explode("\r\n\r\n", $response, 2);
    return $body;
}

// 使用
$body = postXmlSocket('api.example.com', '/orders', $xml);
?>

XML 安全防護

風險說明防護
XXE (XML External Entity)惡意 XML 引用外部實體讀取本地文件/發起內網請求libxml_disable_entity_loader(true) (PHP 8.0+ 預設關閉);simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOENT | LIBXML_DTDLOAD) 禁用實體展開
Billion Laughs (指數級實體擴張)遞歸實體導致記憶體耗盡同上禁用實體;限制輸入大小 post_max_size
XXE 偷帶端口掃描外部實體發起 HTTP 請求探測內網網絡層面限制出站連線;PHP 禁用實體

現代替代:JSON API

除非對接銀行、政府、老舊 ERP 強制要求 XML,**新專案請優先使用 JSON**:

  • 解析速度快 10 倍+(原生 json_decode vs XML 解析器)。
  • 無 XXE 風險、體積小 30-50%、人類可讀、前端原生支援。
  • PHP 陣列 json_encode / json_decode 雙向無損轉換。

結語

PHP 處理 XML 核心:php://input 接收、simplexml_load_string + 禁用實體 解析、cURL 發送並設 Content-Type: application/xml。安全第一:**生產環境必須禁用 XML 外部實體**,否則面臨嚴重 XXE 攻擊風險。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved