PHP SoapClient request - php

I'm trying to send a SOAP request to a newsletter service using this WSDL.
Here's my PHP:
$client = new SoapClient($wsdl_url, array(
'login' => 'myusername',
'password' => 'mypassword',
'trace' => true
));
$client->AddSubscriber(
new SoapParam('MyFirstName', 'FirstName'),
new SoapParam('MyLastName', 'LastName'),
new SoapParam('myemail#someaddress.com', 'Email')
);
I'm getting the exception:
End element 'Body' from namespace 'schemas.xmlsoap.org/soap/envelope/' expected. Found element 'LastName' from namespace ''. Line 2, position 156.
Here's what the service is expecting for AddSubscriber:
<?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="schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<AuthHeader xmlns="admin.ekeryx.com">
<Username>string</Username>
<Password>string</Password>
<AccountID>string</AccountID>
</AuthHeader>
</soap:Header>
<soap:Body>
<AddSubscriber xmlns="admin.ekeryx.com">
<subscriber>
<ID>string</ID>
<FirstName>string</FirstName>
<LastName>string</LastName>
<Email>string</Email>
</subscriber>
<overwritable>boolean</overwritable>
</AddSubscriber>
</soap:Body>
</soap:Envelope>
Here's what's being sent:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="tempuri.org/">
<SOAP-ENV:Body>
<ns1:AddSubscriber/>
<LastName>MyLastName</LastName>
<Email>myemail#someaddress.com</Email>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
I'm not very familar with SOAP, and I've been looking for documentation all over the place, but I can't seem to find a very good reference for what I'm doing.
Any guidance would be very much appreciated!
Thanks. Could you give me an example? I'm looking at the example on the PHP site that shows:
<?php
class SOAPStruct {
function SOAPStruct($s, $i, $f)
{
$this->varString = $s;
$this->varInt = $i;
$this->varFloat = $f;
}
}
$client = new SoapClient(null, array('location' => "http://localhost/soap.php",
'uri' => "http://test-uri/"));
$struct = new SOAPStruct('arg', 34, 325.325);
$soapstruct = new SoapVar($struct, SOAP_ENC_OBJECT, "SOAPStruct", "http://soapinterop.org/xsd");
$client->echoStruct(new SoapParam($soapstruct, "inputStruct"));
?>
Are you saying I would have to create a Subscriber PHP class, assign all the vars $this->FirstName = $first_name, etc... and then put it in a SoapVar with encoding SOAP_ENC_OBJECT? How can I better represent the subscriber structure?

There are two possible Params subscriber and overwriteable
<soap:Body>
<AddSubscriber xmlns="admin.ekeryx.com">
<subscriber>
<ID>string</ID>
<FirstName>string</FirstName>
<LastName>string</LastName>
<Email>string</Email>
</subscriber>
<overwritable>boolean</overwritable>
</AddSubscriber>
So you need to do some more complex construction by using SoapVar to represent the subsrciber structure.
http://www.php.net/manual/en/soapvar.soapvar.php
Should look something like this i think, although youll want to check the XSD against the Soap:Body produced...
$subscriber = new StdClass();
$subscriber->ID = 'myid';
$subscriber->FirstName = 'First';
$subscriber->LastName = 'Last';
$subscriber = new SoapParam(new SoapVar($subscriber, SOAP_ENC_OBJECT, $type, $xsd), 'subscriber');
$type should be the type in the XSD/WSDL defeinition for the api and $xsd is the URI for the XSD.
I think that should do it but Ive only used native PHP libs once for EBay (it was a nightmare haha) and that was almost 2 years ago so im a little rusty.

I came across this while looking for a similar answer myself. I believe the issue you are having is that the following code will pass the login and password in the HTTP header not the SOAP header
$client = new SoapClient($wsdl_url, array(
'login' => 'myusername',
'password' => 'mypassword',
'trace' => true
));
I believe this is what you are looking for
$headerbody = array('Token' => $someToken,
'Version' => $someVersion,
'MerchantID'=>$someMerchantId,
'UserCredentials'=>array('UserID'=>$UserID,
'Password'=>$Pwd));

Related

PHP - SOAP API authentication

I encounter some problems when I try to call a method of api with authentication.
$auth = (object) array(
'user'=>'username',
'password'=>'password',
'company'=> 'companyname'
);
$url = 'https://webservices.gocadservices.com/NVS?wsdl';
$soap = new SoapClient('https://webservices.gocadservices.com/NVS?wsdl',$auth);
echo $soap->nop();
I get an error : The user parameter is empty or missing.
My question : How can I send a request xml like this :
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<xs:nvheader xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:nvcommand>
<xs:user>
username
</xs:user>
<xs:password>
mot de passe
</xs:password>
<xs:company>
companyname
</xs:company>
</xs:nvcommand>
</xs:nvheader>
</soapenv:Header>
</soapenv:Envelope>
I must have this structure so that the API SOAP will work.
Thanks.
You need to set a SOAP Header for this to work:
$nvcommand = (object)[
'user' => 'username',
'password' => 'password',
'company' => 'company'];
$authHeader = new SoapHeader('namespace','nvcommand', $nvcommand);
$soapClient = new SoapClient('http://localhost:44333/SoapService.com?wsdl', $soapOptions);
$soapClient->__setSoapHeaders($authHeader);
$return = $soapClient->__soapCall('HelloWorld',[]);
This will send a SOAP Header
<env:Header>
<ns2:nvcommand>
<user>username</user>
<password>password</password>
<company>company</company>
</ns2:nvcommand>
</env:Header>
along with the Request. The options array in the SoapClient ctor isnt used to pass auth information. Please refer to
https://www.php.net/manual/de/soapclient.construct.php

PHP To Call a SOAP Webservice

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.

How to call overloaded wsdl webservice method from php soap client

Webservice : http://webservices.dishtv.in/Services/Mobile/Trade/TradeSubscriberInfo.asmx
Overloaded method is GetSubscriberInfoV2 MessageName="GetSubscriberInfoVCLogV2"
My php code is,
<?php
$mobileno="01523833622";
$url="http://webservices.dishtv.in/Services/Mobile/Trade/TradeSubscriberInfo.asmx?wsdl";
$client = new SoapClient($url);
$soapHeader = array('UserID' => '47','Password' => 'zZa##286##');
$header = new SOAPHeader('http://tempuri.org/', 'AuthenticationHeader', $soapHeader);
$client ->__setSoapHeaders($header);
try
{
$res = $client->GetSubscriberInfoVCLogV2(array('vcNo' => $mobileno, 'mobileNo' => '', 'BizOps' => '1', 'UserID' => '555300', 'UserType' => 'DL' ));
}
catch(SoapFault $e)
{
echo "Invalid No";
print_r($e);
}
print_r($res);
?>
It gives error GetSubscriberInfoVCLogV2 is not found. I need to get the response of GetSubscriberInfoVCLogV2. Can anyone help me to find the solution.
The only way to do this is writing the XML request manually and sending it through the method SoapClient::__doRequest.
It would be something like this:
$request = <<<'EOT'
<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://tempuri.org/">
<SOAP-ENV:Body>
<ns1:TheMessageNameGoesHere>
<ns1:param1>$param1</ns1:param1>
<ns1:param2>$param2</ns1:param2>
<ns1:param3>$param3</ns1:param3>
</ns1:TheMessageNameGoesHere>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
EOT;
$response = $soapClient->__doRequest(
$request,
"http://www.exemple.com/path/to/WebService.asmx",
"http://tempuri.org/TheMessageNameGoesHere",
SOAP_1_1
);
Change "TheMessageNameGoesHere" for the MessageName found in the WebService description page.
The XML structure can also be found in the WebService description page, when you click in the function.
The third parameter of the method __doRequest is the SOAP action, and can be found in the WSDL file as an attribute of the tag <soap:operation>

Issues with SOAP in non-WSDL mode

I am making a simple web service for communication between two sites I own.
Since it is only a basic application, I've been working without a WSDL file, so in non-WSDL mode as the PHP manual calls it.
This is basically what the client-side looks like:
$client = new SoapClient(null, array('location' => $location, 'uri' => '', 'trace' => TRUE));
$res = $client->__soapCall('myFunc', array($param));
On the server-side, I have a function called myFunc:
$soap = new SoapServer(null, array('uri' => ''));
$soap->addFunction('myFunc');
//Use the request to invoke the service
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$soap->handle();
}
When I actually try invoking the myFunc function, I get and error:
Function 'ns1:myFunc' doesn't exist
For some reason, the soap server is prepending ns1: to the function name!
Using $client->__getLastRequest(), I get:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:getTopElement>
<param0 xsi:type="xsd:string">rightcolBox</param0>
</ns1:getTopElement>
</SOAP-ENV:Body>
I'm not a SOAP expert, but it seems to me that the client is causing the error in making the request - or is the server misinterpreting it?
How can I fix this issue?
I had the same problem. When I set SoapClient options' uri to not null, the problem was solved.
$client = new SoapClient(null, array('location' => $location, 'uri' => 'foo', 'trace' => TRUE));
Yes, it can be any string, even "foo" as in this example.

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