Issues with SOAP in non-WSDL mode - php

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.

Related

PHP soap request with certifcate

$method ='MerchantFinancialOperationWS';
$configs = array(
'soap_version' => SOAP_1_2,
'cache_wsdl' => WSDL_CACHE_NONE,
'exceptions' => false,
'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
'local_cert' => $cert_file,
'passphrase' => $cert_password
);
if($debug) $configs['trace'] = true;
if(substr($url, -5) != '?WSDL') $url.= '?WSDL';
$webService = new SoapClient($url, $configs);
$data = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:fin="http://financial.services.merchant.channelmanagermsp.sibs/">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Action>http://financial.services.merchant.channelmanagermsp.sibs/MerchantFinancialOperationWS/requestFinancialOperationRequest</wsa:Action>
<wsa:ReplyTo>
<wsa:Address>https://enderecodeteste.pt</wsa:Address>
</wsa:ReplyTo>
</soapenv:Header>
<soapenv:Body>
<fin:requestFinancialOperation>
<arg0>
<messageType>N0003</messageType>
<aditionalData>TESTE</aditionalData>
<alias>
<aliasName>351#994999999</aliasName>
<aliasTypeCde>001</aliasTypeCde>
</alias>
<financialOperation>
<amount>400</amount>
<currencyCode>9782</currencyCode>
<operationTypeCode>022</operationTypeCode>
<merchantOprId>11111</merchantOprId>
</financialOperation>
<merchant>
<iPAddress>255.255.255.255</iPAddress>
<posId>880924 </posId>
</merchant>
<messageProperties>
<channel>01</channel>
<apiVersion>1</apiVersion>
<channelTypeCode>VPOS</channelTypeCode>
<networkCode>MULTIB</networkCode>
<serviceType>01</serviceType>
<timestamp>2014-10-31T13:58:49.2934+01:00</timestamp>
</messageProperties>
</arg0>
</fin:requestFinancialOperation>
</soapenv:Body>
</soapenv:Envelope>';
$result = $webService->requestFinancialOperation($data);
I've been trying to implement a soap request with a pem certificate and i'm just getting out of ideas. I know my code should be all wrong but i have no idea what the right direction is. I've been researching but found little no none documentation on this and the team behind the webservice i have to use also wasn't able to help.
I can already communicate with the service using SoapUI so i know the webservice works
Part of the issue is you're sending XML when you may not need to. PHP's built-in SOAP client will handle the XML for you, so you can focus on the objects (the O in SOAP!). You need to construct a data structure (object or array) and pass that to the operation you want to run. First look for the signature of the operation you want using:
$webService = new SoapClient($url, $configs);
var_dump($webService->__getFunctions());
This gives you the API - note that it indicates the data structures it expects in both the input parameters and the output. To see what those data structures look like:
var_dump($webService->__getTypes());
Now you can construct a PHP object with the same fields and structure and pass it in. Your code will look something along these lines:
$webService = new SoapClient($url, $configs);
$parameter = new stdClass();
$parameter->someField = 'N0003';
$parameter->anotherField = 'TESTE';
$result = $webService->requestFinancialOperation($parameter);

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>

PHP get data from soap service

I need to get data from http://ws.jrtwebservices.com/jrtlowfaresearch/jrtlfs.asmx, this service need credential information.such as ID, userid and system value. I put these information into one string:
$xml_post_string = "<POS><Source> <RequestorID Type='21' ID='xxx'/> </Source> <TPA_Extensions> <Provider><System>xxx</System> <Userid>xxx</Userid> </Provider></TPA_Extensions></POS>"
And i also defined SoapClient:
$client = new SoapClient(null, array('uri' => "http://ws.jrtwebservices.com",
'location => "http://ws.jrtwebservices.com/jrtlowfaresearch/jrtlfs.asmx") );
I call soapCall as:
$response = $client->__soapCall('do_LowfareSearch',array($xml_post_string),array('soapaction' => 'http://jrtechnologies.com/do_LowfareSearch'));
Does anybody know why i get empty response?
Thanks very much!
Using your code, the request looks like this:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xm...">
<SOAP-ENV:Body>
<ns1:do_LowfareSearch>
<param0 xsi:type="xsd:string">
"<POS><Source> <RequestorID Type='21' ID='xxx'/> </Source> <TPA_Extensions> <Provider <System>xxx</System> <Userid>xxx</Userid> </Provider></TPA_Extensions></POS>"
</param0>
</ns1:do_LowfareSearch>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The client used the method you passed but could not structure the parameters the way you gave them. All of your parameters are just in " " inside of <param0>.
(Also, you are missing a ' after location. 'location => "http:...)
When you make your SOAP client you want to set the WSDL, it will do all the XML formatting for you.
The WSDL should have the location in it so you do not need to worry about that.
I like to use a WSDL validator to test out the methods and see their parameters.
You should structure the information you want to pass as arrays or a classes and let the SOAP client and WSDL convert it into the XML you need.
So something like this is what you are looking for:
<?php
//SOAP Client
$wsdl = "http://ws.jrtwebservices.com/jrtlowfaresearch/jrtlfs.asmx?WSDL";
$client = new SoapClient($wsdl, array( 'soap_version' => SOAP_1_1,
'trace' => true, //to debug
));
try {
$args = array(
'companyname'=> 'xxx',
'name'=> 'xxx',
'system'=> 'xxx',
'userid'=> 'xxx',
'password'=> 'xxx',
'conversationid'=>'xxx',
'entry'=> 'xxx',
);
$result = $client->__soapCall('do_LowfareSearch', $args);
return $result;
} catch (SoapFault $e) {
echo "Error: {$e}";
}
//to debug the xml sent to the service
echo($client->__getLastRequest());
//to view the xml sent back
echo($client->__getLastResponse());
?>

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

PHP SoapClient request

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));

Categories