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.
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