PHP Soap Complex Data Type? - php

I am trying to consume a PHP Soap service however I seem to have having trouble with a complex/abstract type.
This is the SOAP call generated using SOAP UI :-
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:lin="http://llu.webservices.opalonline.co.uk/LineCharacteristicsWS">
<soapenv:Header/>
<soapenv:Body>
<lin:GetLineCharacteristics>
<lin:request>
<!--Optional:-->
<lin:UserCredentials>
<!--Optional:-->
<!--Optional:-->
<lin:Username>testUser</lin:Username>
<lin:Password>testPass</lin:Password><lin:AgentID>1234</lin:AgentID>
</lin:UserCredentials>
<lin:RequestDetails xsi:type="lin:TelephoneNumberRequest" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<lin:TelephoneNumber>123456789</lin:TelephoneNumber>
</lin:RequestDetails>
<lin:UserConsent>Yes</lin:UserConsent>
<lin:ServiceType>MPF</lin:ServiceType>
</lin:request>
</lin:GetLineCharacteristics>
</soapenv:Body>
</soapenv:Envelope>
Here is my PHP code :-
$call = new StdClass();
$call->request = new StdClass();
$call->request->UserConsent = "Yes";
$call->request->ServiceType = "MPF";
$call->request->UserCredentials = new StdClass();
$call->request->UserCredentials->Username="testUser";
$call->request->UserCredentials->Password="testPass";
$call->request->UserCredentials->AgentID=1234;
$call->request->RequestDetails = new StdClass();
$call->request->RequestDetails->TelephoneNumber = "123456789";
$url = "https://llu.webservices.opalonline.co.uk/LineCharacteristicsWSV6/LineCharacteristicsWS.asmx?wsdl";
$client = new SoapClient($url, array('trace' => 1, exceptions=> 1,'soap_version' => SOAP_1_1));
$result = $client->GetLineCharacteristics($call);
echo $client->__getLastRequest();
echo $client->__getLastResponse();
When I run the code, the following error is generated :-
Fatal error: Uncaught SoapFault exception: [soap:Client] Server was unable to read request. ---> There is an error in XML document (2, 382). ---> The specified type is abstract: name='RequestType', namespace='http://llu.webservices.opalonline.co.uk/LineCharacteristicsWS', at http://llu.webservices.opalonline.co.uk/LineCharacteristicsWS'>. in /Users/jamesormerod/NetBeansProjects/fpdfDev/TestClass.php:23
Can anyone help?

To be able to send the request well formed with correct type and namespace, you must use both classes named as the required elements and a classmap that maps the elements to the classes.
The WsdlToPhp project can help you generate the classes and the classmap. You can use the project at wsdltophp.com.
Then if for example you generate the package with the name LineCharacteristics, you'll be able to send the request using this sample code:
$lineCharacteristicsServiceGet = new LineCharacteristicsServiceGet();
// sample call for LineCharacteristicsServiceGet::GetLineCharacteristics()
$details = new LineCharacteristicsStructTelephoneNumberRequest('+3363136363636');
$request = new LineCharacteristicsStructGetLineCharacteristicsRequest($details, LineCharacteristicsEnumUserConsentEnum::VALUE_YES, LineCharacteristicsEnumServiceTypeEnum::VALUE_MPF);
$userCredentials = new LineCharacteristicsStructCredentials(11111,'********','********');
$request->setUserCredentials($userCredentials);
$characteristics = new LineCharacteristicsStructGetLineCharacteristics($request);
$r = $lineCharacteristicsServiceGet->GetLineCharacteristics($characteristics);
echo implode("\r\n", array($lineCharacteristicsServiceGet->getLastRequestHeaders(),$lineCharacteristicsServiceGet->getLastRequest(),$lineCharacteristicsServiceGet->getLastResponseHeaders(),$lineCharacteristicsServiceGet->getLastResponse()));
if($r)
print_r($lineCharacteristicsServiceGet->getResult());
else
print_r($lineCharacteristicsServiceGet->getLastError());

Related

Soap request working in SoapUI but not in Wordpress plugin

I've been searching around for a solution to my problem, but to no avail. I'm trying to send a soap request through a Wordpress plugin using the following:
function soapRequest($soapUsername, $soapNonce, $soapDateTime, $soapPassword) {
$wsdl = 'http://www.beautyfort.com/api/wsdl/v2/wsdl.wsdl';
$trace = true;
$exceptions = false;
$client = new SoapClient($wsdl, array('trace' => $trace, 'exceptions' => $exceptions));
// Must be a stdClass (and not an array)
$auth = new stdClass();
$auth->Username = $soapUsername;
$auth->Nonce = $soapNonce;
$auth->Created = $soapDateTime;
$auth->Password = $soapPassword;
$header = new SoapHeader('http://www.beautyfort.com/api/', 'AuthHeader', $auth);
$client->__setSoapHeaders($header);
$xml_array['TestMode'] = 'true';
$xml_array['StockFileFormat'] = 'JSON';
$xml_array['SortBy'] = 'StockCode';
try {
$response = $client->GetStockFile($xml_array);
}
catch (Exception $e) {
log_me("Error!");
log_me($e -> getMessage());
log_me('Last response: '. $client->__getLastResponse());
}
log_me('Last request: '. $client->__getLastRequest());
log_me($response);
}
This produces the following request:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns1="http://www.beautyfort.com/api/">
<SOAP-ENV:Header>
<ns1:AuthHeader>
<ns1:Username>joetest</ns1:Username>
<ns1:Nonce>htflFfIKM4</ns1:Nonce>
<ns1:Created>2019-02-09T10:13:51.000Z</ns1:Created>
<ns1:Password>NGFjYTJiNzJmOWY2MzBmY2M2MjJkNjg1MDgyMWRjMzQxOGY1YTNjYQ==</ns1:Password>
</ns1:AuthHeader>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:GetStockFileRequest>
<ns1:TestMode>true</ns1:TestMode>
<ns1:StockFileFormat>JSON</ns1:StockFileFormat>
<ns1:SortBy>StockCode</ns1:SortBy>
</ns1:GetStockFileRequest>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
And I get an invalid credentials error. I've also been testing in SoupUI and the following request works:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:api="http://www.beautyfort.com/api/">
<soapenv:Header>
<api:AuthHeader>
<api:Username>joetest</api:Username>
<api:Nonce>tJrsRlQt6i</api:Nonce>
<api:Created>2019-02-06T23:34:11.000Z</api:Created>
<api:Password>ZTBhMmE5OGY4YTNlZWIzZTE0ZTc2ZjZiZDBhM2RhMjJmNzAxNzYwZA==</api:Password>
</api:AuthHeader>
</soapenv:Header>
<soapenv:Body>
<api:GetStockFileRequest>
<api:TestMode>true</api:TestMode>
<api:StockFileFormat>JSON</api:StockFileFormat>
<!--Optional:-->
<api:FieldDelimiter>,</api:FieldDelimiter>
<!--Optional:-->
<api:StockFileFields>
<!--1 or more repetitions:-->
<api:StockFileField>StockCode</api:StockFileField>
<api:StockFileField>Category</api:StockFileField>
<api:StockFileField>Brand</api:StockFileField>
<api:StockFileField>Collection</api:StockFileField>
<api:StockFileField>Category</api:StockFileField>
</api:StockFileFields>
<api:SortBy>StockCode</api:SortBy>
</api:GetStockFileRequest>
</soapenv:Body>
</soapenv:Envelope>
Now the only differences I can see (apart from the optional fields) is the names of the namespace, and the use of the Xml tag at the top of the request. Both of these shouldn't matter right? I'd really appreciate your help on this as I've been scratching my head for ages.
Thank you in advance!
Your perfect just need to set UTC timezone and secret format like below:
base64 encoded(sha1(Nonce . Created . Secret))

How can I enable WS-RM (version 1.2) with NuSOAP client

Can enable I enable WS-RM (version 1.2) with NuSOAP client just like below? I tried this, but I cannot receive data from the API. Any ideas? Thanks.
$client = new nusoap_client($api_link, array('reliable' => 1.2 , 'useWSA' => TRUE) );
Full Code:
try {
include_once 'WebServiceSOAP/lib/nusoap.php';
$api_link = 'https://www.my-api.com/MYAPI.svc/SSL?wsdl';
$acode = '###';
$uname = '###';
$ttype = '###';
$ccode = '###';
$hpass = '###';
//setting xml request to api
$credentials = '<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/" xmlns:ezr="http://schemas.datacontract.org/2004/07/EzremitAPI.Entities">
<soapenv:Header/>
<soapenv:Body>
<tem:GetLocalRates>
<!--Optional:-->
<tem:credentials>
<!--Optional:-->
<ezr:AgentCode>'.$acode.'</ezr:AgentCode>
<!--Optional:-->
<ezr:HashedPassword>'.$hpass.'</ezr:HashedPassword>
<!--Optional:-->
<ezr:Username>'.$uname.'</ezr:Username>
</tem:credentials>
<!--Optional:-->
<tem:payincurcode>'.$ccode.'</tem:payincurcode>
<!--Optional:-->
<tem:transferType>'.$ttype.'</tem:transferType>
</tem:GetLocalRates>
</soapenv:Body>
</soapenv:Envelope>';
//creating soap object
$client = new nusoap_client($api_link, array('cache_wsdl' => WSDL_CACHE_NONE, 'soap_version' => SOAP_1_2) );
$client->soap_defencoding = 'UTF-8';
$soapaction = "http://tempuri.org/IRateAPI/GetLocalRates";
$xmlobjs = $client->send($credentials, $soapaction);
$err = $client->getError();
if ($err) {
echo '<h2>Constructor error</h2><pre>' . $err . '</pre>';
exit();
}
//print_r($client);
print_r($xmlobjs);
}
catch(Exception $e) {
echo $e->getMessage();
}
?>
I'm not very good at PHP and SOAP. Above code may have errors. Could you please check the code and give me your comments. I have made some amendments after searching Google.
Also, can I run this on PHP 5.4.42? When I run above code, I get below error now.
Constructor error
HTTP Error: Unsupported HTTP response status 415 Cannot process the message because the content type 'text/xml; charset=UTF-8' was not the expected type 'application/soap+xml; charset=utf-8'. (soapclient->response has contents of the response)
If anyone is looking for the answer to my above question, I found the solution with the help from #Marcel.
The answer to the question:
This code is wrong, don't use it.
$client = new nusoap_client($api_link, array('reliable' => 1.2 , 'useWSA' => TRUE) );
NuSoap client is outdated and not supporting to WS-RM. I had to use PHP inbuilt SOAP extension to get my project worked.
Full answer in here: SOAP Error in PHP: OperationFormatter encountered an invalid Message body
Thanks

Send soap xml data in php

Please how can I send the following xml to a remote webservice(**/quick.svc?wsdl) using soap in php
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:quic="http://services.interswitchng.com/quicktellerservice/">
<soapenv:Header/>
<soapenv:Body>
<quic:SendBillPaymentAdvice>
<!--Optional:-->
<quic:xmlParams>
<![CDATA[<BillPaymentAdvice>
<Amount>10000</Amount>
<PaymentCode>145536</PaymentCode>
<CustomerMobile>0856534</CustomerMobile>
<CustomerEmail>luvysols#gmail.com</CustomerEmail>
<CustomerId>Trdfg001</CustomerId>
<TerminalId>2323001</TerminalId>
<RequestReference>123456789</RequestReference>
</BillPaymentAdvice>]]>
</quic:xmlParams>
</quic:SendBillPaymentAdvice>
</soapenv:Body>
</soapenv:Envelope>
The SoapClient class provides a client for SOAP 1.1, SOAP 1.2 servers. It can be used in WSDL or non-WSDL mode.
$url = "";
$client = new SoapClient($url, array("trace" => 1, "exception" => 0));
Ref: http://php.net/manual/en/class.soapclient.php
First Include the nusoap.php and after it add this code.
$sen_code='XML CODE';
$client->debug($headers,$sen_code);
$client->decode_utf8 = FALSE;
$rel_lgoin = $client->call('method_for_call');

How do I make this exact soap call?

To start off with, I am a beginner at soap.
I am trying to make a soap call to a service and was given a working sample that comes from talend. What I need is to make a similar call in PHP.
The output from talend is as follows, (extracted from the HTTP request)
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<root>
<request>
<username>a#a.com</username>
<password>md5sumlookalike</password>
<webservice>GetCust</webservice>
<refid>12343321</refid>
<message>reserv#123</message>
</request>
</root>
</soap:Body>
</soap:Envelope>
So I wrote a little bit of PHP as it works as a scripting language as well for where it will be called from. Trying to understand how to make a soap call I came up with this bit.
<?php
// Yes I know about the diffrent port issue here. So I wgeted and stored it for use next to script
# $soapClient = new SoapClient("http://123.123.123.123:8088/services", array("trace" => true));
$soapClient = new SoapClient("wsdl", array("trace" => true));
$error = 0;
try {
$info = $soapClient->__soapCall("invoke",
array
(
new SoapParam("a#a.com", "username"),
new SoapParam("md5sumish", "password"),
new SoapParam("GetCust", "webservice"),
new SoapParam("1234321", "refid"),
new SoapParam("reserv#123", "message")
)
);
} catch (SoapFault $fault) {
$error = 1;
echo 'ERROR: '.$fault->faultcode.'-'.$fault->faultstring;
}
if ($error == 0) {
print_r($output_headers);
echo 'maybe it worked\n';
unset($soapClient);
}
?>
I end up seeing the following in the HTTP request via wireshark. The server just does not know what to do with this and does not respond. I am unsure what/where I need to go from here.
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://talend.org/esb/service/job">
<SOAP-ENV:Body>
<ns1:invokeInput>a#a.com</ns1:invokeInput>
<password>md5sumish</password>
<webservice>GetCust</webservice>
<refid>1234321</refid>
<message>reserv#123</message>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
So I have to ask is how to get rid of the ns1:invokeInput and make it username. Along with bring the rest of the format into line so the request looks like the output from talend?
Here is a working little script I did in php to call a talend tutorial service exported as soap:
//....
if (sizeof($_POST) > 0) {
$name = $_POST['name'];
$city = $_POST['city'];
$client = new SoapClient("http://192.168.32.205:8080/DirectoryService/services/DirectoryService?wsdl", array( 'trace' => 1));
$result = $client->runJob(array(
'--context_param',
'Name=' . $_POST['name'],
'--context_param',
'City=' . $_POST['city']
));
}
//...
Talend seems to be very "basic" regarding how parameters are given.
With this code it was working fine.

Building a call to a SoapClient in PHP

I am new to SOAP and trying to figure out how to build a call to a SOAP server. Here is the definition of what I am trying to get:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:prov="http://bridgewatersystems.com/xpc/subscribermetering/service/provisioning/">
<soapenv:Header/>
<soapenv:Body>
<prov:GetMeteringStateRequest>
<subscriber subscriber-id="USERID" />
</prov:GetMeteringStateRequest>
</soapenv:Body>
</soapenv:Envelope>
Here is the PHP I am using to test (and not working of course):
$user_id = "REALIDHERE";
$parameters->subscriber_id = $user_id;
$parameters->MIN = "test";
$parameters->partition_key = "test";
try {
$client = new SoapClient("http://SOAPIP:32010/soap/services/SubscriberMeteringProvisionAPI.wsdl");
echo "trying...\n";
print( $client->GetMeteringState( new SoapParam("subscriber", $parameters ) ) );
} catch (SoapFault $e) {
//var_dump($e);
}
Any help on getting the call to GetMeteringState() to work would be great.
Thanks.
I'd recommend checking out the XML that is generated by your request. This is explained pretty well here, but here's an example:
// prepare SoapClient
$client = new SoapClient("http://.../SubscriberMeteringProvisionAPI.wsdl");
print( $client->GetMeteringState( new SoapParam("subscriber", $parameters ) ) );
// output the XML request
echo "<pre>".$client->__getLastRequest()."</pre>";

Categories