我已经多年来一直坚持这个问题,并且在许多小时的搜索之后无法找到解决方案。
我正在使用返回运费的Fedex网络服务。以下是我的PHP代码
try {
$client = new SoapClient($path_to_wsdl, array(
'uri' => 'http://fedex.com/ws/rate/v14',
'location' => 'https://ws.fedex.com:443/web-services/rate',
'soap_version' => 'SOAP_1_1',
'login' => 'myusername', //I don't know whether this is needed but but it is an internal company site
'password' => 'password', //so I log in with this username and pw to see it
'proxy_host' => 'proxy-host-name',
'proxy_port' => 443,
'proxy_login' => '',
'proxy_password' => '',
'trace' => 1,
'exceptions' => 1));
$data = array(
'Action' => "http://fedex.com/ws/rate/v14/getRates"
);
$header = new SoapHeader('http://fedex.com/ws/rate/v14', 'FedexHeader', $data, false);
$client->__setSoapHeaders($header);
if(setEndpoint('changeEndpoint')){
$newLocation = $client->__setLocation(setEndpoint('endpoint'));
}
$response = $client -> getRates($request);
} catch (SoapFault $exception) {
echo '<h2>exception</h2>';
print_r($exception);
echo '<br/><h2>exception trace</h2>';
var_dump($exception->getTraceAsString());
echo '<br/>Request headers : <br/><xmp>',
$client->__getLastRequestHeaders(),
'</xmp><br/>';
echo 'Request : <br/><xmp>',
$client->__getLastRequest(),
'</xmp><br/>';
echo 'Response headers: <br/><xmp>',
$client->__getLastResponseHeaders(),
'</xmp><br/>';
echo 'Response : <br/><xmp>',
$client->__getLastResponse(),
'</xmp><br/>';
printFault($exception, $client);
}
这实际上是来自Fedex的示例代码 - 我更改的唯一部分是wsdl文件的路径名,添加了更多调试信息并设置了SoapHeader。
以下是请求标题:
POST /web-services/rate HTTP/1.1 Host: ws.fedex.com
Connection: Keep-Alive User-Agent: PHP-SOAP/5.3.27
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://fedex.com/ws/rate/v14/getRates"
Content-Length: 2974
和响应标题:
HTTP/1.1 400 Bad Request
Date: Mon, 17 Feb 2014 16:25:56
GMT Server: Apache/2.2
Content-Length: 226
Connection: close
Content-Type: text/html; charset=iso-8859-1
以下是生成的SOAP请求本身的一部分:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://fedex.com/ws/rate/v14" xmlns:ns2="http://www.w3.org/2005/08/addressing">
<SOAP-ENV:Header>
<ns2:Action>http://fedex.com/ws/rate/v14/getRates</ns2:Action>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:RateRequest>
<ns1:WebAuthenticationDetail>
<ns1:UserCredential>
//user credentials
</ns1:UserCredential>
</ns1:WebAuthenticationDetail>
<ns1:ClientDetail>
//client details
</ns1:ClientDetail>
<ns1:RequestedShipment>
//shipping details ..
</ns1:RequestedShipment>
</ns1:RateRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
问题是,当我将此请求粘贴到SOAP UI时,它会返回正确的响应。此外,Fedex支持团队已经确认这是正确的。
这就是为什么我认为它必须是PHP的错误。 (我在很长一段时间内遇到了无法连接到主机的错误 - 我认为这与代理主机有关,但我们的运营团队已经确认此请求现在已经到了代理,所以我认为这已经解决了)
我在其他一些帖子中看到了设置SoapHeader的引用所以我已经这样做了 - 但是我不确定我是否使用了正确的命名空间。另外我想知道我是否应该使用soapAction而不是Action,因为wsdl引用了soapAction?这是wsdl文件中的那部分:
<operation name="getRates">
<s1:operation soapAction="http://fedex.com/ws/rate/v14/getRates" style="document"/>
</operation>
但是,我尝试过使用它们并没有什么区别。此请求也可以在没有soap标头的SoapUI中使用..
更新:我之前确实认为它可能与SSL相关联对Fedex的支持,似乎我不需要使用SSL。
请求在SoapUI中工作的事实确实让我觉得它必须是代码中的东西。
我将非常感谢任何有关如何调试此问题的建议或有关问题的建议。