如何使用 php 通过身份验证调用 Web 服务

How to call web service with auth using php

我需要调用下面的网络服务,但到目前为止未能为其创建代码。

https://www.nightline-delivers.com/ParcelMotel_UAT/RetailService.svc?wsdl

请求需要如下所示:

<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ret="Retail">
   <soapenv:Header>
      <UserName>WebServiceSample</UserName>
      <Password>password</Password>
   </soapenv:Header>
   <soapenv:Body>
      <ret:ValidateCredentials>
         <ret:motelId>BAC032</ret:motelId>
         <ret:mobileNumber>0865596800</ret:mobileNumber>
      </ret:ValidateCredentials>
   </soapenv:Body>
</soapenv:Envelope>

到目前为止,我的代码如下所示:

$client = new SoapClient("https://www.nightline-delivers.com/ParcelMotel_UAT/RetailService.svc?wsdl");

$location = new StdClass();
$location->motelId = 'BAC032';
$location->mobileNumber = '0866696800';

$auth = array(
    'UserName'=>'WebServiceSample',
    'Password'=>'password',
);
$header = new SoapHeader('NAMESPACE','Auth',$auth,false);

$client->__setSoapHeaders( $header );

try {
    $response = $client->ValidateLocation( $location );
    var_dump($response);
} catch( Exception $e ) {
    echo $e->getMessage();
}

根据 this,在 PHP 中不可能获得没有名称空间的 header 元素(在您的示例中就是这种情况),因此使用 SoapClient 是不可能的。但是,您可以尝试发送 UserNamePassword 字段都在 Retail 命名空间中的请求,也许服务器会接受这个:

<?php

$client = new SoapClient("https://www.nightline-delivers.com/ParcelMotel_UAT/RetailService.svc?wsdl", array('trace' => TRUE));

$location = new StdClass();
$location->motelId = 'BAC032';
$location->mobileNumber = '0866696800';

$auth = array(
    'UserName'=>'WebServiceSample',
    'Password'=>'password',
);
$headers = array();
foreach($auth as $k=>$v) {
    $headers[] = new SoapHeader('Retail', $k, $v);
}
$client->__setSoapHeaders( $headers );

try {
    $response = $client->ValidateCredentials( $location );
    var_dump($response);
} catch( Exception $e ) {
    echo "REQUEST: ".$client->__getLastRequest();
    echo $e->getMessage();
}

如果发生异常,此代码也会向您显示请求,并且我已将 ValidateLocation 更改为 ValidateCredentials,如您的示例消息中所示。它产生以下消息:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="Retail">
<SOAP-ENV:Header>
    <ns1:UserName>WebServiceSample</ns1:UserName>
    <ns1:Password>password</ns1:Password>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
    <ns1:ValidateLocation>
        <ns1:motelId>BAC032</ns1:motelId>
        <ns1:mobileNumber>0866696800</ns1:mobileNumber>
    </ns1:ValidateLocation>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

我成功了。这是代码:

<?php

$username = 'WebServiceSample';
$password = 'password';

function formatXML($xml)
{
    libxml_use_internal_errors(true);

    $doc = new DOMDocument();
    $doc->preserveWhiteSpace = false;
    $doc->formatOutput = true;
    $doc->loadXML($xml);

    return $doc->saveXML();
}

try {
    $client = new SoapClient("https://www.nightline-delivers.com/ParcelMotel_UAT/RetailService.svc?wsdl", array(
        'trace' => true,
    ));

    $headers = array();

    $headers[] = new SoapHeader('Retail', 'UserName', 'WebServiceSample');
    $headers[] = new SoapHeader('Retail', 'Password', 'password');

    $client->__setSoapHeaders($headers);

    $params = array(
        'motelId' => 'BAz031',
        'mobileNumber' => '0866696800'
    );

    $result = $client->__soapCall('ValidateLocation', array('ValidateLocation' => $params), array(
        'location' => 'https://www.nightline-delivers.com/ParcelMotel_UAT/RetailService.svc/basic?APIKey=7C3A0EA9-C8D6-4DB0-ADF0-615BFD29DC1D'
    ));

} catch (SoapFault $e) {
    exit($e->getMessage());
}

$request  = $client->__getLastRequest();
$response = $client->__getLastResponse();

echo '<pre>';
echo htmlspecialchars( formatXML($request) );
echo "\n";
echo htmlspecialchars( formatXML($response) );