SOAP call works in SoapUI but fails in PHP using soapclient - Object reference issue

有些话、适合烂在心里 提交于 2019-12-06 12:27:51

问题


Trying to query a .NET webservice hosted on an IIS server using PHP 5.x

$wsdl_path = "http://192.168.1.1/TestSite/TestService.asmx?wsdl";
$soapClient = new SoapClient($wsdl_path, array('trace' => 1));
$dump=var_export($soapClient->__getFunctions(), true);
echo htmlentities($dump);

produces

array (
  0 => 'ProcessTransactionResponse ProcessTransaction(ProcessTransaction $parameters)',
  1 => 'ProcessTransactionResponse ProcessTransaction(ProcessTransaction $parameters)',
)

which would indicate it is correctly accessing the wsdl file.

A correctly formatted query validated using SoapUI is as follows

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.mydomain.tld/">
   <soapenv:Header/>
   <soapenv:Body>
      <ws:ProcessTransaction>
        <!--Optional:-->
         <ws:request>
            <!--Optional:-->
            <ws:Header>
               <!--Optional:-->
               <ws:Token>hello</ws:Token>
            </ws:Header>
            <!--Optional:-->
            <ws:Parameters>
               <ws:DeviceID>12345</ws:DeviceID>
               <ws:SourceScreen>12345</ws:SourceScreen>
               <!--Optional:-->
               <ws:Language>E</ws:Language>
               <ws:LocalDateTime>2015-05-20T11:59:29.910Z</ws:LocalDateTime>
               <ws:TicketID>12345</ws:TicketID>
               <ws:PayScreenAttributeID>12345</ws:PayScreenAttributeID>
               <!--Optional:-->
               <ws:InputValue>1234556789</ws:InputValue>
               <ws:PaymentAmount>0</ws:PaymentAmount>
               <!--Optional:-->
               <ws:POSReceiptCustomer>?</ws:POSReceiptCustomer>
               <!--Optional:-->
               <ws:POSReceiptMerchant>?</ws:POSReceiptMerchant>
            </ws:Parameters>
         </ws:request>
      </ws:ProcessTransaction>
   </soapenv:Body>
</soapenv:Envelope>

So to replicate this with PHP and SoapClient I collect the data elements in an array

$inputParams=array(
    'Token' => 'hello',
    'DeviceID' => 12345,
    'SourceScreen' => 12345,
    'Language' => 'E',
    'LocalDateTime' => '2015-05-20T11:59:29.910Z',  
    'TicketID' => 12345,
    'PayScreenAttributeID' => 12345,
    'InputValue' => '123456789',
    'PaymentAmount' => 0,
    'POSReceiptCustomer' => '?',
    'POSReceiptMerchant' => '?',
);

and perform the query

try {
    $response = $soapClient->__soapCall('ProcessTransaction', array('parameters' => $inputParams));
    var_dump($response);
} catch (SoapFault $fault) {
    var_dump($fault);
    echo "SOAP Fault: (faultcode: {$fault->faultcode}, faultstring: {$fault->faultstring})";
    echo "REQUEST:\n" . htmlentities($soapClient->__getLastRequest()) . "\n";
}

I get the dreaded Server was unable to process request. ---> Object reference not set to an instance of an object. which isn't very useful.

When I look at the __getLastRequest() output, it appears to show the wrapper but none of the query elements

REQUEST:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://ws.mydomain.tld/"><SOAP-ENV:Body><ns1:ProcessTransaction/></SOAP-ENV:Body></SOAP-ENV:Envelope>

I have tried both with and without the Token element to no avail, as well as initially leaving out optional fields (which work fine in the SoapUI interface) but no joy there either.

I suspect that it is related to the additional header container with the Token element as our other soap implementations have not included this element.


回答1:


You're probably right about the header being the cause, or at least part of it. I am not currently within easy reach of a soap server, but I hope the below can at least give some pointers.

There are two possibilities here: either the header should be included as a SoapHeader object, or you need to build your parameters array differently. I'll list both versions.

Either way, you can probably skip the __soapCall() method and use the magic method instead, since you appear to be using wsdl.

Parameters version (try this first)

If you're lucky, you just need to reformat the body in order to suit the given schema. It honestly kinda looks like that. Something like this:

$params = array(
    'request' => array(
        'Header' => array(
            'Token' => 'hello'
        ),
        'Parameters' => array(
            'DeviceID' => 12345,
            'SourceScreen' => 12345,
            'Language' => 'E',
            'LocalDateTime' => '2015-05-20T11:59:29.910Z',  
            'TicketID' => 12345,
            'PayScreenAttributeID' => 12345,
            'InputValue' => '123456789',
            'PaymentAmount' => 0,
            'POSReceiptCustomer' => '?',
            'POSReceiptMerchant' => '?'
        )
    )
);

$wsdl_path = "http://192.168.1.1/TestSite/TestService.asmx?wsdl";
$soapClient = new SoapClient($wsdl_path, array('trace' => 1));
$response = $soapClient->ProcessTransaction($params);

SoapHeader version

What you need to do if you actually do need a proper header is to create an header object and attach it to the client you've instantiated. Then, you can call the endpoint.

In order to do so you need to know the namespace, which should be called targetNameSpace in your schema. You'll also need to know the name, which you can see in e.g. SoapUI.

Finally, it should be enough to just supply the parameters straight away - no need to put them in a single-element array. So you end up with something like the below. With any luck, that may at least put you in the right direction. :)

// instantiate soap client
$wsdl_path = "http://192.168.1.1/TestSite/TestService.asmx?wsdl";
$soapClient = new SoapClient($wsdl_path, array('trace' => 1));

// create and attach a header
$header = new SoapHeader($namespace, $name, array('Token' => 'hello'));
$soapClient->__setSoapHeaders($header);

// call the endpoint
$response = $soapClient->ProcessTransaction($inputParams);
var_dump($response); // hopefully you get something back...


来源:https://stackoverflow.com/questions/30582417/soap-call-works-in-soapui-but-fails-in-php-using-soapclient-object-reference-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!