PHP To Call a SOAP Webservice - php

i would like some help please.
I am trying to call a webservice using PHP and i am having problems with different kind of messages.
The WSDL is "http://195.144.16.7/ElastrakEDI/ElastrakEDI.asmx?WSDL" and the Web Service is Called GetPartMaster. The username and password at first are both TESTUID and TESTPWD ( for testing purposes ).
The XML Below is the Request
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:edi="http://elastrak.gr/edi/">
<soap:Header>
<edi:AuthHeader>
<!--Optional:-->
<edi:Username>TESTUID</edi:Username>
<!--Optional:-->
<edi:Password>TESTPWD</edi:Password>
</edi:AuthHeader>
</soap:Header>
<soap:Body>
<edi:GetPartMaster/>
</soap:Body>
</soap:Envelope>
This XML is the response
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Header>
<AuthHeader xmlns="http://elastrak.gr/edi/">
<Username>TESTUID</Username>
<Password>TESTPWD</Password>
</AuthHeader>
</soap:Header>
<soap:Body>
<GetPartMasterResponse xmlns="http://elastrak.gr/edi/">
<GetPartMasterResult>
<elastrakPartMasterFile xmlns="">
<PartMasterURL>http://195.144.16.7/elastrakEDI/Temp/Parts/OTWKOJL4.txt</PartMasterURL>
<ErrorCode/>
<ErrorDescription/>
</elastrakPartMasterFile>
</GetPartMasterResult>
</GetPartMasterResponse>
</soap:Body>
</soap:Envelope>
I have tried the php code below but still cant get it to work
<?php
$wsdl = 'http://195.144.16.7/ElastrakEDI/ElastrakEDI.asmx?WSDL';
$trace = true;
$exceptions = true;
$xml_array['Username'] = 'TESTUID';
$xml_array['Password'] = 'TESTPWD';
$client = new SoapClient($wsdl, array('trace' => $trace, 'exceptions' => $exceptions));
$client = new SoapClient($wsdl);
$response = $client->GetPartMaster($xml_array);
try
{
$client = new SoapClient($wsdl, array('trace' => $trace, 'exceptions' => $exceptions));
$response = $client->GetPartMaster($xml_array);
}
catch (Exception $e)
{
echo "Error!";
echo $e -> getMessage ();
echo 'Last response: '. $client->__getLastResponse();
}
$response = $response->GetPartMaster->PartMasterURL;
var_dump($response);
?>
Thank you again for your time and Help.

Your request is currently wrongly constructed as you must take into account that therse is actually thow parts in the request:
the SOAP header, containing the username and password
the SOAP body, containing the GetPartMaster element
Take a look to the SoapClient class and the __setSoapHeaders method.
This is why I strongly advise you to use a WSDL to PHP generator to send SOAP Request as it will allow you to easily construct the request and then handle the response while using the OOP approach and not wondering how to send the parameters. Using the generated PHP SDK and a good IDE such as PhpStorm or any Eclipse based IDE with autocompletion, it'll be easy to find your way. Try the PackageGenerator project.

Related

Create Soap Auth request in PHP

I'm new with SOAP and trying to connect it with PHP but without positive results. Maybe you can give me a hand
SOAP 1.2 Request
POST /XXXservice.asmx HTTP/1.1
Host: XXX.prueba.com
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<GetAcData xmlns="https://prueba.com/">
<Userid>string</Userid>
<Password>string</Password>
</GetAcData>
</soap12:Body>
</soap12:Envelope>
SOAP 1.2 Response
HTTP/1.1 200 OK
Content-Type: application/soap+xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
<soap12:Body>
<GetAcDataResponse xmlns="https://prueba.com/">
<XX>xml</GetAcDataResult>
</GetAcDataResponse>
</soap12:Body>
</soap12:Envelope>
I used the following code but I'm getting this message:
SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://XXX.YYYY.com/XXXservice.asmx' : Premature end of data in tag html line 3
<?php
$options = array(
'Userid' => 'xx',
'Password' => 'xx',
);
$client = new SoapClient("https://XXX.YYYY.com/XXXservice.asmx", $options);
$result = $client('GetAcData');
?>
First of all you need an endpoint url of your webservice, that provides you the wsdl content. As #camelsWrittenInCamelCase has written in his comment, you should try https://XXX.YYYY.com/XXXservice.asmx?wsdl instead of https://XXX.YYYY.com/XXXservice.asmx.
Next you should wrap all your soap client stuff in a try/catch block, to get all possible exceptions and the most informations in case of an error.
try {
$client = new \SoapClient(
'https://XXX.YYYY.com/XXXservice.asmx?wsdl',
[
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => true,
'soap_version' => SOAP_1_2,
'trace' => true,
]
);
} catch (\SoapFault $fault) {
echo "<pre>";
var_dump($fault);
echo "</pre>";
echo "<pre>";
var_dump($client->__getLastRequest());
echo "</pre>";
echo "<pre>";
var_dump($client->__getLastResponse());
echo "</pre>";
}
As shown in the example above the soap client is initialized with an options array. We use the trace option, to enable tracing for getting the last send request and response. Additionally wie use the exception option, to force the client to throw exceptions in case of any error. Further more we disable caching the wsdl settings as long as you are developing. If you are going into production, this option should be set to WSDL_CACHE_DISK or WSDL_CACHE_MEMORY.
Now you need to know, which functions and types (complex types) your webservice provides. For this purpose you can do the following.
// getting the functions of your webservice
echo "<pre>";
var_dump( $client->__getFunctions() );
echo "</pre>";
// getting the types of your webservice
echo "<pre>";
var_dump( $client->__getTypes() );
echo "</pre>";
Since I do not know the exact scope of your web service, I'll just assume that the webservice delivers a method called DetAcData with two parameters Userid and Password. With this informations I can only guess, how the right call could look like. For detailed informations I 'd need the output of __getFunctions() and __getTypes().
An examplary call could look like this.
try {
$client = new \SoapClient(
'https://XXX.YYYY.com/XXXservice.asmx?wsdl',
[
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => true,
'soap_version' => SOAP_1_2,
'trace' => true,
]
);
$data = new \stdClass();
$data->Userid = 'YourUserId';
$data->Username = 'YourUsername';
$result = $client->GetAcData($data);
// $result will be an object
echo "<pre>";
var_dump($result);
echo "</pre>";
} catch (\SoapFault $fault) {
// error handling
}
Further more you can write data objects for every complex type mentioned in the functions and types output from your webservice. You can add a classmap to the options array when instantiating your soap client, so that every response and request will automatically be parsed in the corresponding data object. How soap client classmaps work is explained in the php documentation.
Just have a try. I 'm sure you will get it on your own. ;)

Guzzle ClientException - Invalid XML data

I need to send a post request with Guzzle for a project I am working on and keep getting a 400 Bad request error with the message 'Invalid XML Data'. I tried lots of different combinations as far as the settings go and am getting the same error message in all cases.
Did anyone else run into this issue? Any ideas why this is? I appreciate any help in advance.
$xml = $this->getXml();
$client = new GuzzleHttp\Client();
try {
$credentials = base64_encode('username:pass');
$res = $client->post('https://www.example.com',['headers' => ['Content-Type' => 'text/xml; charset=UTF8', 'Authorization' => 'Basic '.$credentials], 'body' => $xml]);
} catch (\GuzzleHttp\Exception\ClientException $e) {
dd($e->getResponse()->getBody()->getContents());
}
For the $xml value, I tried the following:
$xml = '<?xml version="1.0" encoding="utf-8" ?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetCustomerInfo xmlns="http://tempUri.org/">
<CustomerID>1</CustomerID>
<OutputParam />
</GetCustomerInfo>
</soap:Body>
</soap:Envelope>';
My main objective for the time being is to simply resolve this specific client error for invalid XML and reach the server.
The XML looks good, so the code should work. Do you have more details in the response? Maybe position in the XML or something else.
Just a side note: you can use auth option instead of setting Authentication header by hands.

Wrong SOAP Tags in PHP SOAP Request

I'm trying to send an SOAP request.
My request looks like this
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="someurl">
<SOAP-ENV:Body>
<RequestIndBApplication>
But my customer told me it has to look like this
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<process xmlns="someurl">
<RequestIndBApplication>
I'm using an WSDL file i got from my customer. But i don't know how i can change the soap tag. is there a way to do this?
Here is my php code
$client = new SoapClient('urlofwsdlfile',array('trace' => true, 'exceptions' => true)); $params = new \SoapVar($xmlstr), \XSD_ANYXML);
$result = $client->__SoapCall('process', array($params));
$xmlstr contains the data as xml

SOAP request in PHP in CURL

It's have been already several days since I'm trying to figure out SOAP but no success :( Any chance to know how can I create PHP(curl) SOAP request to look like this?
POST /WebServices/domain.asmx HTTP/1.1
Host: webservices.domain.ru
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://www.domain.ru/GetVariants"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<AuthentificationHeader xmlns="http://www.domain.ru/">
<Login>string</Login>
<Password>string</Password>
<PartnerId>string</PartnerId>
</AuthentificationHeader>
</soap:Header>
<soap:Body>
<GetVariants xmlns="http://www.domain.ru/">
<RequestParameters>xml</RequestParameters>
</GetVariants>
</soap:Body>
</soap:Envelope>
Also I have following data:
WSDL:
http://webservices.domain.ru/WebServices/domainXml.asmx?WSDL
Soap action:
http://webservices.domain.ru/WebServices/domainXml.asmx?op=GetVariants
Basically:
PHP's support for SOAP just sucks.
You need to use your WSDL to generate your PHP classes, so you can build a Request object.
You will get something like this:
class SomeClass
{
var $name; //NCName
}
class SomeOtherClass
{
var $value; //anonymous2
}
.
.
.
There are some WSDL to PHP scripts out there. (Google wsdl to php)
Then you do something like this.
$soapClient = new SoapClient($this->_wsdlUrl, array(
'trace' => true,
'exceptions' => true,
'uri' => $this->_endPoint,
'location' => $this->_endPoint,
'local_cert' => $this->certificatePath,
'allow_self_signed' => true,
'soap_version' => SOAP_1_2,
));
// Build the SOAP client object, with your properties.
//After that, you have to call:
$yourContainerObject = new YourContainerObject(); // The top SOAP XML node
$yourContainerObject->SomeChildNode = new SomeChildNode();
$yourContainerObject->SomeChildNode->Name = 'John';
.
.
.
$soapResponse = $soapClient->GetVariants($yourContainerObject);
print_r(soapResponse); // to see what you get
The "GetVariants" method doesn't need to be implemented, so you don't get confused and ask yourself where do I get that from.It is described in WSLD and PHP's SOAP client knows that it is just a SOAP action.
This should be an more advanced example of creating SOAP requests via PHP.
I hope you get the basic flow of this.

simple php SoapClient example for paypal needed

Could I get a simple example of using PHP's SoapClient class to make an empty call to Paypal with nothing but the version number? I have the correct WSDL url and server url, so that's not what I need help with. This is what I have:
public function SOAPcall($function, $args=array()) {
$args['Version'] = '63.0';
$args = new SoapVar($args, SOAP_ENC_ARRAY, $function.'_Request');
$args = array(new SoapVar($args, SOAP_ENC_ARRAY, $function.'_Req', 'urn:ebay:api:PayPalAPI'));
$results = $this->soapClient->__soapCall($function, $args, array('location' => $this->activeKeys['certificate']), $this->soapOptions);
}
I hope it's okay I am not showing everything. The body of the request comes out completely wrong, as you can see below:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns1="urn:ebay:api:PayPalAPI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns2="urn:ebay:apis:eBLBaseComponents">
<SOAP-ENV:Header>
<ns1:RequesterCredentials>
<ns2:Credentials>
<ns2:Username>xxx</ns2:Username>
<ns2:Password>xxx</ns2:Password>
<ns2:Signature>xxx</ns2:Signature>
</ns2:Credentials>
</ns1:RequesterCredentials>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:GetBalanceReq xsi:type="ns1:GetBalance_Req">
<xsd:string>63.0</xsd:string>
</ns1:GetBalanceReq>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
It should look like this:
<?xml version=”1.0” encoding=”UTF-8”?>
<SOAP-ENV:Envelope xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:SOAP-ENC=”http://schemas.xmlsoap.org/soap/encoding/”
xmlns:SOAP-ENV=”http://schemas.xmlsoap.org/soap/envelope/”
xmlns:xsd=”http://www.w3.org/2001/XMLSchema”
SOAP-ENV:encodingStyle=”http://schemas.xmlsoap.org/soap/encoding/”
><SOAP-ENV:Header>
<RequesterCredentials xmlns=”urn:ebay:api:PayPalAPI”>
<Credentials xmlns=”urn:ebay:apis:eBLBaseComponents”>
<Username>api_username</Username>
<Password>api_password</Password>
<Signature/>
<Subject/>
</Credentials>
</RequesterCredentials>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<specific_api_name_Req xmlns=”urn:ebay:api:PayPalAPI”>
<specific_api_name_Request>
<Version xmlns=urn:ebay:apis:eBLBaseComponents”>service_version
</Version>
<required_or_optional_fields xsi:type=”some_type_here”> data
</required_or_optional_fields>
</specific_api_name_Request>
</specific_api_name_Req>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Of course, Paypal throws a "Version is not supported" error.
This is the cleanest solution I could come up with:
$client = new SoapClient( 'https://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl',
array( 'soap_version' => SOAP_1_1 ));
$cred = array( 'Username' => $username,
'Password' => $password,
'Signature' => $signature );
$Credentials = new stdClass();
$Credentials->Credentials = new SoapVar( $cred, SOAP_ENC_OBJECT, 'Credentials' );
$headers = new SoapVar( $Credentials,
SOAP_ENC_OBJECT,
'CustomSecurityHeaderType',
'urn:ebay:apis:eBLBaseComponents' );
$client->__setSoapHeaders( new SoapHeader( 'urn:ebay:api:PayPalAPI',
'RequesterCredentials',
$headers ));
$args = array( 'Version' => '71.0',
'ReturnAllCurrencies' => '1' );
$GetBalanceRequest = new stdClass();
$GetBalanceRequest->GetBalanceRequest = new SoapVar( $args,
SOAP_ENC_OBJECT,
'GetBalanceRequestType',
'urn:ebay:api:PayPalAPI' );
$params = new SoapVar( $GetBalanceRequest, SOAP_ENC_OBJECT, 'GetBalanceRequest' );
$result = $client->GetBalance( $params );
echo 'Balance is: ', $result->Balance->_, $result->Balance->currencyID;
This produces the following XML request document, which, at the time of writing, was being successfully accepted and processed by PayPal:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="urn:ebay:apis:eBLBaseComponents" xmlns:ns2="urn:ebay:api:PayPalAPI"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Header>
<ns2:RequesterCredentials>
<ns1:Credentials xsi:type="Credentials">
<Username>***</Username>
<Password>***</Password>
<Signature>***</Signature>
</ns1:Credentials>
</ns2:RequesterCredentials>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns2:GetBalanceReq xsi:type="GetBalanceRequest">
<GetBalanceRequest xsi:type="ns2:GetBalanceRequestType">
<ns1:Version>71.0</ns1:Version>
<ns2:ReturnAllCurrencies>1</ns2:ReturnAllCurrencies>
</GetBalanceRequest>
</ns2:GetBalanceReq>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
In response to some of the other comments on this page:
I'm fairly certain the OP has read the API doc, because that's where the example XML came from that he is trying to reproduce using PHP SOAP library.
The PayPal PHP API has some shortcomings, the biggest one being that it fails to work with E_STRICT warnings turned on. It also requires PEAR, so if you are not currently using PEAR in your project it means dragging in quite a lot of new code, which means more complexity and potentially more risk, in order to achieve what should be two or three fairly simple XML exchanges for a basic implementation.
The NVP API looks pretty good too, but I'm a glutten for punishment, so I chose the hard path. :-)
Did you check out the API's provided by PayPal here? And a direct link to the PHP SOAP API download.
And here is a link to the NVP API which PayPal recommends you use.
PHP has a very easy to use soapClass.
Which can be found here.
http://www.php.net/manual/en/class.soapclient.php

Categories