如何将SoapClient HTTP内容类型设置为application / soap + xml

时间:2018-10-17 01:15:48

标签: php soap

我需要将内容类型从“ text / xml; charset = utf-8”更改为“ application / soap + xml; charset = utf-8”。

我正在使用PHP默认存在的SoapClient类将请求从PHP发送到另一台服务器(Oracle服务器)。我正在使用PHP v7.0.10。

根据SoapClient文档,我应该将options数组内的soap_version设置为SOAP_1_2,它将更改内容类型,但不会这样做。

SOAP请求

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:pub="http://xmlns.oracle.com/oxp/service/PublicReportService">
    <soap:Header/>
    <soap:Body>
        <pub:runReport>
            <pub:reportRequest>
                <pub:reportAbsolutePath>/Human Capital Management/Workforce Management/Human Resources Dashboard/Fusion User Information.xdo</pub:reportAbsolutePath>
                <pub:sizeOfDataChunkDownload>-1</pub:sizeOfDataChunkDownload>
            </pub:reportRequest>
        </pub:runReport>
    </soap:Body>
</soap:Envelope>

PHP代码

$WSDL = "https://example.com/xmlpserver/services/ExternalReportWSSService?WSDL";

    $soap_options = array(
        'uri' => 'http://www.w3.org/2003/05/soap-envelope',
        'style' => SOAP_RPC,
        'use' => SOAP_ENCODED,
        'soap_version' => SOAP_1_2,
        'cache_wsdl' => WSDL_CACHE_NONE,
        'connection_timeout' => 30,
        'trace' => true,
        'encoding' => 'UTF-8',
        // 'exceptions' => true,
        'location' => $WSDL,
        'login' => '---',
        'password' => '---'
    );

    try {
        $soap_client = new SoapClient(NULL, $soap_options);
        $result = $soap_client->__doRequest($soap_request, $WSDL, "run", NULL);
        $clean_xml = str_ireplace(['SOAP-ENV:', 'SOAP:', 'env:'], '', $result);
        $xml = simplexml_load_string($clean_xml);
        var_dump($xml);
    } catch (Exception $e) {
        echo $e;
    }

最后一个请求标头显示

POST /xmlpserver/services/ExternalReportWSSService?WSDL HTTP/1.1
Host: example.com
Connection: Keep-Alive
User-Agent: PHP-SOAP/7.0.10
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 510
Authorization: Basic ---

我试图通过多种方式设置内容类型,但每种方式都失败了

更新和解决方案

<?php

    $soap_request = <<<XML
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:pub="http://xmlns.oracle.com/oxp/service/PublicReportService">
    <soap:Header/>
    <soap:Body>
        <pub:runReport>
            <pub:reportRequest>
                <pub:reportAbsolutePath>/Human Capital Management/Workforce Management/Human Resources Dashboard/Fusion User Information.xdo</pub:reportAbsolutePath>
                <pub:sizeOfDataChunkDownload>-1</pub:sizeOfDataChunkDownload>
            </pub:reportRequest>
        </pub:runReport>
    </soap:Body>
</soap:Envelope>
XML;

$WSDL = "https://example.com/xmlpserver/services/ExternalReportWSSService?WSDL";
    $user = "---";
    $password = "---";
$ch = curl_init(); 
    curl_setopt($ch, CURLOPT_HEADER,         false);
    curl_setopt($ch, CURLOPT_URL,            $WSDL);
    curl_setopt($ch, CURLOPT_FAILONERROR,    true); 
    curl_setopt($ch, CURLOPT_HTTPHEADER,     Array(
        'Content-Type: application/soap+xml; charset=utf-8', 
        'SOAPAction: "run"',
        'Accept: text/xml',
        'Cache-Control: no-cache',
        'Pragma: no-cache',
        'Content-length: '. strlen($soap_request),
        'User-Agent: PHP-SOAP/7.0.10'
    ));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
    curl_setopt($ch, CURLOPT_USERPWD,        $user.":".$password);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
    curl_setopt($ch, CURLOPT_TIMEOUT,        30);
    curl_setopt($ch, CURLOPT_POSTFIELDS,     $soap_request);
    $response = curl_exec($ch); 
    if (empty($response)) { 
        throw new SoapFault('CURL error: '.curl_error($ch), curl_errno($ch)); 
    } 
    curl_close($ch);
    var_dump($response);
?>

1 个答案:

答案 0 :(得分:1)

摘自SoapClient手册:

  

stream_context选项是上下文的资源。

您可以在新创建的流上下文中设置HTTP标头

$stream_context_opts = array(
    'http'=>array(
        'method'=>"POST",
        'header'=> "Content-Type: application/soap+xml; charset=utf-8\r\n"
    )
);

$soap_stream_context = stream_context_create($stream_context_opts);


 $soap_options = array(
    'uri' => 'http://www.w3.org/2003/05/soap-envelope',
    'style' => SOAP_RPC,
    'use' => SOAP_ENCODED,
    'soap_version' => SOAP_1_2,
    'cache_wsdl' => WSDL_CACHE_NONE,
    'connection_timeout' => 30,
    'trace' => true,
    'encoding' => 'UTF-8',
    'stream_context' => $soap_stream_context,
    // 'exceptions' => true,
    'location' => $WSDL,
    'login' => '---',
    'password' => '---'
);

还有另一种方法,可以通过创建子类并覆盖__doRequest方法

class MySoapClient extends SoapClient { 
    public function __construct($wsdl, $options = array()) {
        parent::__construct($wsdl, $options); 
    }
    public function __doRequest($request,$location,$action,$version,$one_way = 0) { 
        $handle = curl_init(); 
        curl_setopt($handle, CURLOPT_HEADER, false); 
        curl_setopt($handle, CURLOPT_URL, $location); 
        curl_setopt($handle, CURLOPT_FAILONERROR, true); 
        curl_setopt($handle, CURLOPT_HTTPHEADER, Array('Content-Type: application/soap+xml; charset=utf-8') ); 
        curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); 
        curl_setopt($handle, CURLOPT_POSTFIELDS, $request); 
        $response = curl_exec($handle); 
        if (empty($response)) { 
            throw new SoapFault('CURL error: '.curl_error($handle),curl_errno($handle)); 
        } 
        curl_close($handle); 
        return $response;
    } 
}