Sending xml via soapclient in PHP - php

I am very new to using Web Services and understanding XML. If you feel I should read some tutorials or documentation I'd be greatful if you could supply some links.
I am trying to execute a simple function via a web service,
In the documentation that was provided I have the following information...
Web Service Input Parameters:
id , data type = xs:string , lenght: 10
password , data type = xs:string , lenght: 25
group , data type = xs:string , length: 20
orderxml , data type = xs:string , length: 2^16
I have been given sample xml for the last paramater , when I try and run the function I get the following error.
Fatal error: Uncaught SoapFault exception: [a:InternalServiceFault]
Value cannot be null. Parameter name: property in
$client = new SoapClient('http://www.example.com/service?wsdl');
$xml = '<samplexml> </samplexml>';
$response = $client->Import(
array(
'Id' => '1234',
'password' => '123456',
'group' => 'test1',
'orderxml' => $xml
));
When I try
$response = $client->Import('test', 'test');
I get the following...
I tried the second one thinking perhaps I need to send raw XML?
Fatal error: Uncaught SoapFault exception: [a:DeserializationFailed]
The formatter threw an exception while trying to deserialize the
message: Error in deserializing body of request message for operation
'Import'. End element 'Body' from namespace
'http://schemas.xmlsoap.org/soap/envelope/' expected. Found element
'param1' from namespace ''. Line 2, position 162. in

Adrian -
From the snippets you gave, there is not much to determine about what you are trying to do. Without knowing the exact nature of the WSDL, it is hard to say what is going on - is Import a valid request, is it in the right format, etc.
I suggest loading your WSDL into SOAPUI and verifying that your XML format is correct. This is a very useful tool in preparing your SOAP requests before actually coding them in PHP.
http://www.soapui.org/
I would then suggest referencing the PHP manual for the SoapClient class to properly format your code.
http://php.net/manual/en/class.soapclient.php

Related

PHP SoapClient returns null even thought there was a response

Using the PHP SoapClient, I make a call to the WSDL at https://webservices-test.ede.de:9443/ibis/ws/WS_EXT_ELC?wsdl and I get the following xml response (as indicated by $soapclient->__last_response)
<?xml version='1.0' encoding='UTF-8'?><soap:Envelope xmlns:ede="http://ede.de/webservices" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:soap="http://www.w3.org/2003/05/soap-envelope"><soap:Body><Response action="ELC" requestId="1" version="1.0"><created>2017-09-04T16:04:46.556+02:00</created><StatusInformation>OK</StatusInformation><StatusCode>0</StatusCode><Payload><SalesOrderSimulateConfirmation><Items><Item><ID>10</ID><ProductID>0003062700050</ProductID><Price>2.970</Price><PositionPrice>2.970</PositionPrice><PriceUnit>1</PriceUnit><QuantityUnit>ST</QuantityUnit><QuantityAvailable>1</QuantityAvailable><QuantityProfile>1</QuantityProfile><Currency>EUR</Currency><Services /><Schedules>Geplante Liefertermine: 1 ST in KW 36.2017;</Schedules><Remark /><DangerMaterial /></Item></Items></SalesOrderSimulateConfirmation></Payload></Response></soap:Body></soap:Envelope>
Nevertheless, the call to $soapclient->simulateOrder() returns null.
How do I get the PHP SoapClient to return an object instead of null?
Note: The xml I use for the soap call is generated manually by an override to SoapClient::__doRequest(). The code for the soap call looks like:
$soapClient = new SoapClient('https://webservices-test.ede.de:9443/ibis/ws/WS_EXT_ELC?wsdl', array(
'cache_wsdl' => WSDL_CACHE_NONE,
'trace' => true,
'exceptions' => true,
'soap_version' => SOAP_1_2,
'features' => SOAP_SINGLE_ELEMENT_ARRAYS,
'login' => '------', // cannot post here for security purposes
'password' => '-----', // cannot post here for security purposes
'stream_context' => (
stream_context_create(array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
))
));
$result = $soapClient->simulateOrder();
No exceptions are thrown, but $result is null
The problem is the SSL setup, the error that is thrown when I try to call your code on my server is as follows:
Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://webservices-test.ede.de:9443/ibis/ws/WS_EXT_ELC?wsdl' : failed to load external entity "https://webservices-test.ede.de:9443/ibis/ws/WS_EXT_ELC?wsdl" in /home/repojarilo/public_html/sc.php:22 Stack trace: #0 /home/repojarilo/public_html/sc.php(22): SoapClient->SoapClient('https://webserv...', Array) #1 {main} thrown in ... on line 22
I am assuming you are trying to get the code to work with a self signed certificate as indicated in your SSL array inside of the request, however it looks like the SoapClient is not paying attention to it and throwing an error anyway.
So my solution would be to either buy an SSL (very cheap now days, try sites such as namecheap etc...) or use something like https://letsencrypt.org/ to obtain an SSL that will allow your soap client to work correctly.
Lastly I noticed a typo, in your code one line before last you have )); which should read )));.
Koda
The Problem is that SOAP needs a valid SSL-Certificate.
For an testing-server it's sometimes not worth the effort, so maybe this link help you to use a little workarround, to got your SOAP-Request working without need to create a fully-validated SSL-Certificat:
http://automationrhapsody.com/send-soap-request-over-https-without-valid-certificates/
Problem is not your certificate as client, but server certificate itself (try to load https://webservices-test.ede.de:9443/ibis/ws/WS_EXT_ELC?wsdl in a browser), that is invalid. You can ignore it perfectly, as server certificate it's mainly to avoid phishing, and I understand that url it's really the one you're attempting to reach. In command line curl, this is realized with the -k option. In php, SoapClient exactly, you can use this (exactly your problem, check third answer, and see what says about PHP7)
NOTE: You are loading wsdl, the definition file of the service, at each construction of SoapClient. If you store $soapclient as a static variable, you can use it's methods all the time without the need of recreate the client object (and so, avoiding to reload and reinterpret the wsdl file, that can delay perfectly from 1 to 5 seconds) all the time.

Access wcf service with custome binding using php soapclient

I have a wcf service and I can access that using soapclient in php, Now I am going to use load balancer and this article is saying 'set false to keepAliveEnabled'. Therefore I used customeBindings. but the issue is now I can not access the service using php. I saw many articles saying use basicHttpBindings, but I can not use that method. I am getting this error.
Caught exception: Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-16LE'.
Therefore I added soapversion to SoapClient
$client = new SoapClient($wsdl, array('uri' => 'http://tempuri.org/','soap_version' => SOAP_1_2,'trace' => true,'cache_wsdl' => WSDL_CACHE_NONE,'keep_alive' => false));
then I am getting this error.
Caught exception: The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://Microsoft.ServiceModel.Samples/Service1'
This is the customBinding I used.
<customBinding>
<binding name="HttpBinding" keepAliveEnabled="False"/>
</customBinding>
Can anyone tell me how to resolve this. Or any other way to do this. Thanks

Object reference not set to an instance of an object error when trying SOAP call

I am trying to connect to and authenticate with a webservice using SOAP / wsdl, but I constantly get the error:
<b>Fatal error</b>: Uncaught SoapFault exception: [a:InternalServiceFault] Object reference not set to an instance of an object. in /path/install.php:16
Below is my current code:
<?php
header("Content-Type: text/plain");
$userinfo = array(
'Username'=>'test',
'Password'=>'test'
);
$wsdl_url = 'https://ws-e-distribution.kmd.dk/standard/ServiceAutorisation/ServiceAutorisation.svc?wsdl';
$client = new SoapClient($wsdl_url);
print_r($client->__getFunctions());
print_r($client->__getTypes());
//This is the problematic line:
$response = $client->__soapCall('LogOn', array('LogOn' => $userinfo));
var_dump($response);
I have tried every possible way of wrapping the username and password parameters that I could conceive of or find anyone suggesting:
using a custom class
using a stdClass
using SoapVar
using SoapParam
using a simple array
double wrapped array
A lot of combinations of the above.
And I've tried calling the function like $client->__soapCall('LogOn', [milliontries]) as well as $client->LogOn([milliontries])
...nothing works, please help.
Update:
I finally managed to get a different error (that suggests at least I hit upon something slightly less wrong). My code now looks like this:
$response = $client->LogOn(array('logon' => array('Username' => 'test','Password' => 'test')));
Which gives me an error about the LogOnType being unsupported (in Danish, which suggests to me that at least I have some sort of connection to the server now). The username and password array has no effect, I can substitute an empty string and get the same result, the thing that makes the difference is the lowercase logon.
If anyone can set up a working example that gives the error incorrect username or password I will be forever grateful... but any pointers will be much appreciated.
As far as I understand the wsdl gives all the information needed to do this, I'm just too much of a [your_pick] to get it...?
Unbelievable ! It only took nine hours to write these 16 lines of code.
<?php
header("Content-Type: text/plain");
$userinfo = array(
'Username'=>'test',
'Password'=>'test'
);
$wsdl_url = 'https://ws-e-distribution.kmd.dk/standard/ServiceAutorisation/ServiceAutorisation.svc?wsdl';
$client = new SoapClient($wsdl_url, array('trace' => 1, "exception" => 0));
print_r($client->__getFunctions());
print_r($client->__getTypes());
//This actually works ! :) :) :)
$response = $client->LogOn(array('logon' => new SoapVar($userinfo, SOAP_ENC_OBJECT, 'LogOnUsername', 'http://schemas.datacontract.org/2004/07/WebServiceAutorisation.BL')));
var_dump($response);
I was so close several times, and it turned out the namespace (the URL) was the magic bit I was missing. I had been using the namespace from the main wsdl (or no namespace at all) in every attempt at using SoapVar's.
Well now, on to the actual purpose of logging in, probably won't be any easier

PHP error when try execute .net webservice method

I need communicate with web-service construct in .net(i think), but when i try call a method, return this error:
The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://tempuri.org/TripointWebservicesVersionedGeneral/Ping'.
Code to connect to web-service and execute method:
$client = new SoapClient(
'...?wsdl',
array(
'trace' => 1,
'soap_version' => SOAP_1_2
)
);
//$test = $client->__soapCall('Ping',array(''));
$test = $client->Ping();
What is the reason of this error? or what i need to do to call a method?
I have already read this PHP Fatal error: "The SOAP action specified on the message, '', does not match the HTTP SOAP Action", and put in option of soap connection this "'action' => '.../Ping'" but don't help me.
i've found the reason why i can't call the method's, its because of this:
One of the problems:
The PHP returns "Caught exception: Cannot process the message because the content type ‘text/xml; charset=utf-8′ was not the expected type ‘application/soap+xml; charset=utf-8′."
The reason:
WCF is running a new version of web services than expected by the PHP.
The solution:
Change the binding type of the WCF service from binding="wsHttpBinding" to binding="basicHttpBinding".
This insures that your .NET web service would support clients and other services that conform to the WS-I standards.
url source:
http://spacebug.com/php-calling-wcf-part-1-html
Not a full answer, but I just wanted to highlight that you're probably facing this problem because you're using SoapClient to try and consume a web service that uses WS-Addressing. You should try to track down what others do in this situation:
http://www.cdatazone.org/index.php?/archives/15-WS-Addressing-for-extsoap.html
https://github.com/wso2/wsf

How to call overloaded SOAP method with PHP SoapClient?

Confluence soap api defines two methods with the same name but different parameters:
Page getPage(String token, long pageId) - returns a single Page (according to the documentation the second parameter is String, but in WSDL it is long)
Page getPage(String token, String spaceKey, String pageTitle) - returns a single Page
I would need to call the method with two parameters using PHP SoapClient. In WSDL mode SoapClient insists on using the three-parameter one. In non-WSDL mode I managed to make a call with two parameters, but I cannot make the type of the second parameter to be long. How can I get the SoapClient to call getPage with two parameters with the correct types?
Here's what I've done so far:
Using SoapClient in WSDL mode...
$soapClient = new SoapClient("http://xxx/confluence/rpc/soap-axis/confluenceservice-v1?wsdl", array("trace" => TRUE));
$token = $soapClient->login(CONFLUENCE_USERNAME, CONFLUENCE_PASSWORD);
$page = $soapClient->getPage($token, $confluence_article_id);
...produces a request for the three-parameter method (only body shown)...
<SOAP-ENV:Body><ns1:getPage><in0 xsi:type="xsd:string">dkjLIx00Ap</in0><in1 xsi:type="xsd:string">24445207</in1><in2 xsi:nil="true"/></ns1:getPage></SOAP-ENV:Body>
...which causes fault:
<faultstring>com.atlassian.confluence.rpc.RemoteException: You're not allowed to view that page, or it does not exist.</faultstring>
The page with that ID does exist and I am allowed to see it, which I can confirm by making the correct kind of request with SoapUI.
Using SoapClient is non-WSDL mode...
$soapClient = new SoapClient(null, array(
"location" => "http://xxx/confluence/rpc/soap-axis/confluenceservice-v1",
"uri" => "http://soap.rpc.confluence.atlassian.com",
"trace" => TRUE));
$token = $soapClient->login(CONFLUENCE_USERNAME, CONFLUENCE_PASSWORD);
$page = $soapClient->getPage($token, $confluence_article_id);
...produces a request for the two-parameter method with incorrect type for the second parameter. When $confluence_article_id is string, the request is...
<SOAP-ENV:Body><ns1:getPage><param0 xsi:type="xsd:string">8Or94ZLqe7</param0><param1 xsi:type="xsd:string">24445207</param1></ns1:getPage></SOAP-ENV:Body>
...which returns the same fault as above:
<faultstring>com.atlassian.confluence.rpc.RemoteException: You're not allowed to view that page, or it does not exist.</faultstring>
When $confluence_article_id is integer, the request is...
<SOAP-ENV:Body><ns1:getPage><param0 xsi:type="xsd:string">y0kF4z0m9L</param0><param1 xsi:type="xsd:int">24445207</param1></ns1:getPage></SOAP-ENV:Body>
...which returns a different kind of fault:
<faultstring>org.xml.sax.SAXException: Bad types (int -> class java.lang.String)</faultstring>
If I take the request, change int to long and try it with SoapUI, it works just fine.
I have also tried to call it using __soapCall, but the results are similar:
$page = $soapClient -> __soapCall('getPage', array('in0'=>$token,'in1'=>$confluence_article_id));
There is a related PHP bug report and another one, and discussion on Atlassian forums, but none of them helped me.
So far the best suggestion has been to tweak the WSDL by removing the other getPage definition and saving it locally somewhere.
If I remember correctly you can call the function using an associative array instead ex:
//Page getPage(String token, String spaceKey, String pageTitle)
$soapClient->getPage(array("token" => $token,"spaceKey" => $spaceKey,"pageTitle" => $pageTitle));
Not tested, standard warnings apply

Categories