Creating the right SOAP call in PHP - php

I'm having trouble creating the right SOAP call in PHP. I've tested the following call in SOAP UI and it works, but I've tried everything from creating objects, arrays and SOAPHeaders and I can't seem to get the right call. Here is the request that works in SOAP UI:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:com="com.dtn.aghost.API.subscriptions">
<soapenv:Header>
<com:ServiceCredentials>
<usernamePasswordCombo>
<username>[username]</username>
<password>[password]</password>
</usernamePasswordCombo>
</com:ServiceCredentials>
</soapenv:Header>
<soapenv:Body>
<com:SubscriptionServiceIdList>
<visible>1</visible>
</com:SubscriptionServiceIdList>
</soapenv:Body>
</soapenv:Envelope>
Thanks!

I had some questions as your request has very little information regarding what you've already tried. I suggest you add some of the code that you have attempted to use and some of the resources you've looked at to get that information. In addition it would help to answer your request if you described the results of what you tried. Such as were there errors if so what errors did you see?
A good place to look to get examples of PHP code connecting to a SOAP web service would be the PHP documentation about the Soap Client.
In the comments of that page you will find examples of code that others have used. You may be adapt that to use that for your purposes.
As for an example of code connecting to a SOAP web service
<?php
$http_client = 'http://example.com/MyService.asmx?wsdl';
$client = new SoapClient($http_client, array(
'style' => SOAP_DOCUMENT,
'use' => SOAP_LITERAL,
'soap_version'=>SOAP_1_1,
'trace' => 1,
'connection_timeout' => 300));
$params = array( 'username' => $user_name, 'password' => $password);
$results = $client->myFunction($params);
// Debug code can be added after this
?>
Another thing that you will need to do is debug the results of the request. In the example above it sets the value of trace to 1. This allows you to debug the SOAP request that has taken place. You can do that with the following code.
// Debug code
echo $client->__getLastRequestHeaders();
echo $client->__getLastRequest()
echo $client->__getLastResponseHeaders();
echo $client->__getLastResponse();
PHP SoapClient getLastResponse
Last of all you can use is_soap_fault to determine if the request failed. There are some good code examples on the PHP documentation for getting the error code of what happened.

Related

Soap insert request xml format from powershell

i'm trying to make a soap service that is capable of inserting certain values into a microsoft sql database, the server is php and the client calls the server from powershell.
So i have a Soap server setup with NuSOAP and a number of methods, these methods are made like this:
$server->register('InsertInDb',
array('query' => 'xsd:string'), // parameter
array('return' => 'xsd:string'), // output
'urn:server', // namespace
'urn:server#helloServer', // soapaction
'rpc', // style
'encoded', // use
'the query you want to execute');
now i can call this method with the following code from the powershell client:
$url = ".../NuSoapServerTest.php?wsdl"
$proxy = New-WebServiceProxy $url
$proxy | gm -memberType Method
$proxy.InsertInDb('Insert into value etc...')
however i want to be able to execute a method like this
$url = ".../NuSoapServerTest.php?wsdl"
$soap = [xml]#'
<?xml version="1.0" encoding="utf8"?>
<soap:Envelope xmlns:xsi=".../NuSoapServerTest.php?wsdl">
<soap:Body>
<inventory>
<machine>
<systemname>example value</systemname>
</machine>
<hardware>
<machine_type>example value</machine_type>
</hardware>
</inventory>
</soap:Body>
</soap:Envelope>
'#
$ret = Execute-SOAPRequest $soap $url;
with each <'tag'> meaning a layer in the database.
i've been looking around the web a lot for examples but as of yet i haven't found any examples that make it clear to me how i can set either the server or client up to execute my methods in the demonstrated way.
Maybe i am misunderstanding the principals of SOAP and how its supposed to work or i'm just being dumb but any help would be appreciated
edit: it might be worth noting this is the first time i am working with powershell.

PHP SOAP client with authentication required in function call

I'm completely new to using SOAP, and am looking to create some client software connecting to an existing service that provides no resources/demo's for PHP. I'd like to determine if I'm doing something wrong with my code, or if it's perhaps a systems issue (I've created an Apache2.4/PHP7.2.7 on Windows Server 2008 R2 environment).
I've already spent hours going testing things and going through the numerous other SOAP/PHP topics on here, and the point of distinction I've where I'm making my own thread is that the authentication is required in the SoapClient call but rather the $client->__soapCall(function, params)call.
First this is what I have in PHP.
$customerArray = array( $cust1 , $cust2, $cust3 );
$credentials = array(
'login' => $login,
'password' => $password,
);
try{
$client = new SoapClient($soaplink);//, $credentials);
} catch (Exception $e) {
echo "<h2>Exception Error in SoapClient</h2>";
echo $e->getMessage();
}
var_dump($client->__getFunctions());
try{
$response = $client->__soapCall("getCustomers", array($customerArray, $credentials));
}catch (Exception $e) {
echo "<h2>Exception Error in soapCall</h2>";
echo $e->getMessage();
}
var_dump($response());
The first try block completes, with or without the credentials array. The second try block when trying to call the function returns the exception "looks like we got no XML document".
The SOAP service provided demo XML files, the one for this function looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:getCustomers
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns1="http://ws.praxedo.com/2008_07_01/customermodel/service"
>
<in0
soapenc:arrayType="soapenc:string[3]"
xsi:type="soapenc:Array" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
>
<in0 xsi:type="soapenc:string">CUSTOMER001</in0>
<in0 xsi:type="soapenc:string">CUSTOMER002</in0>
<in0 xsi:type="soapenc:string">CUSTOMER003</in0>
</in0>
<in1
xsi:type="soapenc:string"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
>
login|password
</in1>
</ns1:getCustomers>
</soapenv:Body>
</soapenv:Envelope>
WSDL files were also provided, it could be I need to load from that but following a demo to do so provided no results. I could include some of the WSDL here but I believe the XML provides all the relevant details?
So can anyone see if there's something I'm doing wrong here in my PHP, or should what I'm doing work and I need to look into the client Apache/SOAP server side?
I strongly advise you to use a WSDL to PHP generator as it'll allow you to construct the request without any wondering (depending on your PHP knowledge level at the least).
Try the PackageGenerator project. You have to install it then generate the PHP SDK. The generated SDK uses composer and contains all the classes and methods required to send any request. Take a look to the auto-generated tutorial.php file which is a good starting point.

complete noob, SOAP PHP, request with authentication, store in mySQL

OK, so I'm completely lost here! Been staring myself blind at the screen for two days and all the explanations/tutorials I can find on the internet assumes you've already worked with SOAP before.
Using SOAPui I was at least able to try out the request and see the result :) But I need to replicate this in PHP... e.g, make request in PHP using authentication credentials and then store the response in a mySQL table.
This is how the request looks like
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
<soapenv:Header/>
<soapenv:Body>
<tem:DoThis>
<tem:licensId>[MYLICENSID]</tem:licensId>
<tem:licenskey>[MYLICENSKEY]</tem:licenskey>
<tem:guid>[AGUID]</tem:guid>
</tem:DoThis>
</soapenv:Body>
</soapenv:Envelope>
So I need to verify/authenticate the request (i guess)? But how do I do this with PHP?
Once I get the request to work, how will the response be presented? I would like to insert it into an existing mySQL DB. That is to say that this is my "end game"/the purpose of this. Retrieving information from external system, compare it to existing information in DB, and if new information exists, replace current or add new.
I tried
$wsdl = 'http://URLTOSERVICE/Export.svc?wsdl';
$client =
new SoapClient(
$wsdl,
array(
"tem:licensid" => "[MYLICENSID]",
"tem:licenskey" => "[MYLICENSKEY]",
"tem:guid" => "[AGUID]"
)
);
print_r($client->DoThis());
But the response is about as interesting as looking in to a blank paper for 2 days... i.e, returns nothing.
Like I said in the topic title and at the beginning. I have no experience with SOAP. So please, if some kind soul out there takes the time to answer, keep in mind that I need clear and precise explanations :)
And thank you to anyone taking the time to help me understanding this...
can you indicate the WSDL url? I would suggest you to try a WSDL to php converter to see more clearly how to call the SOAP Web service.
To set credentials as the request you indicate, you must use the Soapheader class, http://php.net/manual/fr/class.soapheader.php, and call the __setSoapheaders, http://www.php.net/manual/fr/soapclient.setsoapHeaders.php, before calling the operation.
Let me know if you need any help or a WSDL to php converter.

wsdl service response once variables are sent, php

I am new to SOAP WSDL FUNCTIONS. I have a client who has been given a wsdl file from a company that deals in car testing. My client is a subcontractor for them. They have told us to upload the information about the car plate, category etc and once the details are sent through,There will be a response from server of either success or failure. Kindly assist in this.
Browsing through different information, I tried to do something like below but it is not working
<?php
$data = array('1'=>'value','2'=>'value','3'=>'value','4'='value','5'=>'value');
$wsdl ='http://181.24.80.32/ws/services/servicename';
$client = new SoapClient($wsdl);
$response = $client->servicenamerequest($data);
echo $response->servicenamereturn;
?>
First of all: Go get SoapUI if you are dealing with an unknown Soap service. SoapUI will read the WSDL file and allow you to look at nearly everything related to Soap methods, parameters, and return values (if you dare to make a call to the live service - hopefully there is a sandbox server that does nothing critical).
But SoapUI can help you there by creating a mock service that receives your request and responds with a canned request that you prepared. Here's how I got from your linked WSDL to a working code example without touching the real service.
Setting up SoapUI
Create a new project in SoapUI and give the location of the WSDL. You might name this project.
SoapUI then reads the contents of the WSDL and creates the project containing all described requests. After that you see what methods the service offers, and what kind of parameters have to go into it, as a tree. Opening this tree will get you to "Request 1" for every method detected, which displays some XML in the free version (paid version is slightly more comfortable with a form to fill) like this (from the vehiclePassedTest method):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tr="http://tr.gov.tp.stp.ws.PassedVehicleTestService">
<soapenv:Header>
<tr:password>?</tr:password>
<tr:username>?</tr:username>
</soapenv:Header>
<soapenv:Body>
<tr:vehiclePassedTest>
<chassisNo>?</chassisNo>
<plateNo>?</plateNo>
<plateCode>?</plateCode>
<plateCategory>?</plateCategory>
<plcEmiCode>?</plcEmiCode>
<currentUserName>?</currentUserName>
</tr:vehiclePassedTest>
</soapenv:Body>
</soapenv:Envelope>
The questionmarks are where you have to provide data. This request structure has to be created by you using the SoapClient of PHP.
Let's mock this. Mocking means that SoapUI starts it's own Soap server that accepts requests. It usually runs on 127.0.0.1:8080. Right-click on the project "PassedVehicleTestService" and select "New MockService". Accept the name, press Ok.
Right-click on the method you want to mock. Select "Add to mock service" and select the created one from the previous step. Answer yes to open the mock response editor. There you see the XML structure of the answer, with question marks for the data that the service will fill out. All the responses from this service allow one answer as a string, so write something nice that will be returned. You can add the other methods to this service later if needed.
Right-click your "MockService 1" and select "Start minimized". This will start the Soap server, it will wait for an incoming request.
Setup PHP SoapClient for the mock.
You need to know two things. First the location of the WSDL. This file contains the address of the real server to be used for the requests, but PHP allows to override this. So the second info you need is the address of the running mock service.
SoapUI displays the address from the WSDL in the request editor. In your case it is http://181.24.80.32/ws/services/PassedVehicleTestService - the mock service runs on http://127.0.0.1:8080/ws/services/PassedVehicleTestService - IP and port is replaced, the path is kept.
This leads to the first lines of PHP code:
$options = array(
'location' => 'http://127.0.0.1:8080/ws/services/PassedVehicleTestService',
);
$client = new SoapClient("http://www.quickregistration.ae/temp/PassedVehicleTestService.xml", $options);
After that you have a configured SoapClient able to talk to your mock service. If later you want to use the real service, throw the line with "location" out of the array, and keep the other config parameters if you happen to add some.
Talk to the mock
With the client, you can do $client->nameOfSoapMethod(paramStructure). The parameter structure usually is a mixture of arrays or objects and scalar values like strings. So that's what I try first:
$result = $client->vehiclePassedTest(array());
var_dump($result);
Then I look at SoapUI to see what happens. Output from the php script:
Notice: Array to string conversion in [...]/soap.php on line 20
string(1) "?"
SoapUI says:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tr.gov.tp.stp.ws.PassedVehicleTestService">
<SOAP-ENV:Body>
<ns1:vehiclePassedTest>
<chassisNo>Array</chassisNo>
<plateNo/>
<plateCode/>
<plateCategory/>
<plcEmiCode/>
<currentUserName/>
</ns1:vehiclePassedTest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
That was not the right approach. The array got converted into a string "Array", and was placed as the first parameter. The rest is empty. Nice, because I know that soap calls may accept more that one parameter, and this is one of these services.
$result = $client->vehiclePassedTest('chassisNo', 'plateNo', 'plateCode', 'plateCategory', 'plcEmiCode', 'currentUserName');
This shows up correctly in SoapUI, but the headers are still missing.
Adding SoapHeader to the request
The SoapClient offers a method named __setSoapHeaders(), and there is a class SoapHeader.
The description says that setSoapHeaders() accepts one SoapHeader object or an array of SoapHeader objects. Let's create one, pass it and see what happens:
$username = new SoapHeader();
$client->__setSoapHeaders($username);
$result = $client->vehiclePassedTest('chassisNo', 'plateNo', 'plateCode', 'plateCategory', 'plcEmiCode', 'currentUserName');
var_dump($result);
PHP says: Warning: SoapHeader::SoapHeader() expects at least 2 parameters, 0 given
$username = new SoapHeader('namespace', 'username', 'MyUserName');
This works. SoapUI says:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tr.gov.tp.stp.ws.PassedVehicleTestService" xmlns:ns2="namespace">
<SOAP-ENV:Header>
<ns2:username>MyUserName</ns2:username>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:vehiclePassedTest><chassisNo>chassisNo</chassisNo><plateNo>plateNo</plateNo><plateCode>plateCode</plateCode><plateCategory>plateCategory</plateCategory><plcEmiCode>plcEmiCode</plcEmiCode><currentUserName>currentUserName</currentUserName></ns1:vehiclePassedTest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Note the TWO xmlns attributes in the SOAP-ENV:Envelope element. The original request requires the username be in the namespace "tr" - but "tr" is only a shortcut to the string that is defined as "xlmns:tr" - the string behind this is your namespace needed (although it might already work with the real service).
$username = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'username', 'myUser');
$password = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'password', 'yetAnotherPassword');
$client->__setSoapHeaders(array($username, $password));
This correctly defines the headers, as you can see:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tr.gov.tp.stp.ws.PassedVehicleTestService">
<SOAP-ENV:Header>
<ns1:username>myUser</ns1:username>
<ns1:password>yetAnotherPassword</ns1:password>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:vehiclePassedTest><chassisNo>chassisNo</chassisNo><plateNo>plateNo</plateNo><plateCode>plateCode</plateCode><plateCategory>plateCategory</plateCategory><plcEmiCode>plcEmiCode</plcEmiCode><currentUserName>currentUserName</currentUserName></ns1:vehiclePassedTest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
No two namespaces in the envelope element, and every element is of namespace "ns1". This should work.
Your final code:
$options = array(
'location' => 'http://127.0.0.1:8080/ws/services/PassedVehicleTestService',
);
$client = new SoapClient("http://www.quickregistration.ae/temp/PassedVehicleTestService.xml", $options);
$username = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'username', 'myUser');
$password = new SoapHeader("http://tr.gov.tp.stp.ws.PassedVehicleTestService", 'password', 'yetAnotherPassword');
$client->__setSoapHeaders(array($username, $password));
$result = $client->vehiclePassedTest('chassisNo', 'plateNo', 'plateCode', 'plateCategory', 'plcEmiCode', 'currentUserName');
var_dump($result);
try something like this. Works for me.
try {
$client = new SoapClient("http://wsdl", array('trace' => 1));
$data = $client->someFunction(array('parma1' => 'value1', 'param2' => 'value2'));
print_r($data);
} catch (SoapFault $fault) {
trigger_error("SOAP Fault: (faultcode: {$fault->faultcode}, faultstring: {$fault->faultstring})", E_USER_ERROR);
exit();
}
And check is you have installed php-soap package in your server.
Greatings.

Set attributes for parameters in SOAP request PHP

I'm trying to use a webservice which only allows SOAP request
as far as I know I must create a request that looks like this
<?xml version="1.0" encoding="utf-8"?>
<SessionCreateRQ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<POS>
<Source PseudoCityCode="SECRET_CODE" />
</POS>
</SessionCreateRQ>
however while adding the parameter to SessionCreateRQ method I don't know how to add the POS parameter called Source and have no clue on how to set the attribute for that parameter
im trying the following in php
$body = array(
'POS' => array('source' => 'PseudoCityCode:SECRET_CODE'));
try
{
$result = $c->SessionCreateRQ($body);
}
but no luck, does anyone has a clue on how should I construct this call properly ?
thanks !
Firstly you need WSDL definition for this service (online or in local file). Any not bad SOAP service provide WSDL to users.
Secondly you need translate WSDL service definition to PHP-code. Try wsdl2php generator. Its generate file with classes, that making calls to web-services.
Your example will be approximately as follows:
require_once 'GeneratedTypes.php';
$client = new SOAPService();
$res = $client->SessionCreateRQ(SECRET_CODE);
p.s. wsdl2php not ideal but it is working :)

Categories