can't get soapUI into PHP function - php

I have been struggling for hours now on a SOAP connection and can't get it to work, this is what I have:
$url = 'https://xxx/connector.svc?singleWsdl';
$user = 'user';
$pass = 'pass';
$options = array(
'uri'=>'http://schemas.xmlsoap.org/soap/envelope/',
'style'=>SOAP_RPC,
'use'=>SOAP_ENCODED,
'soap_version'=>SOAP_1,
'cache_wsdl'=>WSDL_CACHE_NONE,
'connection_timeout'=>15,
'trace'=>true,
'encoding'=>'UTF-8',
'exceptions'=>true,
);
try {
$soapclient = new SoapClient($url, $options);
# $soapclient = new SoapClient($url);
}
catch(Exception $e) {
die($e->getMessage());
}
I tried '?wdsl' but then I get:
PHP Fatal error: SOAP-ERROR: Parsing WSDL: <message> 'IConnector_GetProduct_ServiceFaultFault_FaultMessage' already defined
A request with no parameters works fine:
$result = $soapclient->GetVersionInfo();
$last_request = $soapclient->__getLastRequest();
$last_response = $soapclient->__getLastResponse();
print "Request: ".$last_request ."\n";
print "Response: ".$last_response."\n";
print_r($result);
Result:
Request: <?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="Unit4.AgressoWholesale.Connectors"><SOAP-ENV:Body><ns1:GetVersionInfo/></SOAP-ENV:Body></SOAP-ENV:Envelope>
Response: <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetVersionInfoResponse xmlns="Unit4.AgressoWholesale.Connectors"><GetVersionInfoResult xmlns:a="http://schemas.datacontract.org/2004/07/Unit4.AgressoWholesale.Common.Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><a:FullVersion>14.4.18.0</a:FullVersion><a:Release>14</a:Release><a:ServicePack>4</a:ServicePack><a:Fix>18</a:Fix><a:Version>0</a:Version><a:CustomCode/><a:AWBuild>38</a:AWBuild><a:AWFix>003</a:AWFix><a:AWCustomBuild/><a:AWCustomFix/><a:AWCustomCustomerCode/></GetVersionInfoResult></GetVersionInfoResponse></s:Body></s:Envelope>
stdClass Object
(
[GetVersionInfoResult] => stdClass Object
(
[FullVersion] => 14.4.18.0
[Release] => 14
[ServicePack] => 4
[Fix] => 18
[Version] => 0
[CustomCode] =>
[AWBuild] => 38
[AWFix] => 003
[AWCustomBuild] =>
[AWCustomFix] =>
[AWCustomCustomerCode] =>
)
)
So far so good, but the trouble begins trying to log in, which is a must.. In SoapUI it works with:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:unit="Unit4.AgressoWholesale.Connectors" xmlns:unit1="http://schemas.datacontract.org/2004/07/Unit4.AgressoWholesale.Common.Contracts">
<soapenv:Header/>
<soapenv:Body>
<unit:Login>
<unit:SecurityContext>
<unit1:SessionToken></unit1:SessionToken>
<unit1:UserId>user</unit1:UserId>
<unit1:Password>pass</unit1:Password>
</unit:SecurityContext>
</unit:Login>
</soapenv:Body>
</soapenv:Envelope>
But converting this to PHP, I'm stranding here.. this is what I have tried:
$data = array( 'SecurityContext' => array( 'SessionToken' => ''
,'Password' => $user
,'UserId' => $pass)
);
$data = array( 'SessionToken' => ''
,'Password' => $user
,'UserId' => $pass
);
$data = new stdClass;
$data->SecurityContext = new stdClass;
$data->SecurityContext->SessionToken = '';
$data->SecurityContext->UserId = $pass;
$data->SecurityContext->Password = $user;
#$result = $soapclient->__call('Login',array($data));
#$result = $soapclient->Login($data);
$result = $soapclient->__soapCall('Login',array($data));
But no matter what I try, event without parameters or an empty array or stdClass, I get:
PHP Fatal error: Uncaught SoapFault exception: [s:ServiceFault] An exception occurred
It's driving me nuts, I can't find anything on the internet about the fatal exeption '[s:ServiceFault]'
What am I doing wrong? Any help will be greatly appreciated!

OK, writing out the problem sometimes is enough to get to an anwer!
The solution was two-fold:
1) get better error reporting by using a try{} catch:
try {
$result = $soapclient->__call('Login',array($data));
#$result = $soapclient->Login($data);
#$result = $soapclient->__soapCall('Login',array($data));
} catch (SoapFault $e) {
$error = $e->faultcode;
echo str_replace('>',">\n",$error) ;
}
$last_request = $soapclient->__getLastRequest();
$last_response= $soapclient->__getLastResponse();
print "\nRequest: " .str_replace('>',">\n",$last_request);
print "\nResponse: ".str_replace('>',">\n",$last_response);
That way I got just that litle more information I needed! to:
2) enter password in the password field and the username in the user field
It works!
For those interested
Using the array structure and the 'new stdClass' both work
all three ways of parsing the call work (also the two commented out ones, use which one you like)

Related

Problem with sending array via Soap WSDL - PHP

I have problem with send SOAP query. For some reason my code [numerNadania] isn't good. I guess it's some problem with structure.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:e=http://e-nadawca.poczta-polska.pl
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header/>
<soapenv:Body>
<e:addReklamacje>
<reklamowanaPrzesylka
dataNadania="2018-05-22"
urzadNadania="260578"
powodReklamacjiOpis="TEST TEST TEST"
odszkodowanie="0" oplata="0" oczekiwaneOdszkodowanie="0">
<przesylka
guid="262A34BA2C1111116237B659B312F5EB"
numerNadania="00159007738099827991"
opis="TEST"
planowanaDataNadania="2018-05-22"
xsi:type="e:przesylkaBiznesowaType"/>
<powodReklamacji
idPowodGlowny="4"
powodGlownyOpis="TEST TEST TEST">
<powodSzczegolowy
idPowodSzczegolowy="9" powodSzczegolowyOpis="TEST TEST TEST"/>
</powodReklamacji>
</reklamowanaPrzesylka>
</e:addReklamacje>
</soapenv:Body>
</soapev:Envelope>
$options["login"] = "***";
$options["password"] = "***";
$options["soap_version"] = SOAP_1_2;
$wsdl = 'en.wsdl';
try {
$client = new SoapClient($wsdl,$options);
}
catch(Throwable $e) {
echo 'Wystąpił problem z połączniem API';
}
$params = array(
'reklamowanaPrzesylka' => array (
'przesylka' => array (
'guid' => getGuid(),
'numerNadania' => $id,
),
'powodReklamacji' => "Czas dostawy",
)
);
$problem = $client->addReklamacje($params);
stdClass Object ( [errorNumber] => 13250 [errorDesc] => Numer nadania dla składanych reklamacji jest wymagany [guid] => F8CF816CDF4DD8151116C0EE340C4031 )
Numer nadania dla składanych reklamacji jest wymagany - Send number is required [TRANSLATE]
In the past i have been using wsdl2php converters to create client code that resolves most of this type of issues.
See this one for example: https://github.com/rquadling/wsdl2php
They all work pretty much the same, you need to provide ?wsdl endpoint, run script and it will produce client code and output it in to file. Than you can include file and use generated classes and methods.
Hope this helps.

Parse XML SOAP to Object JSON with PHP 7

I have the following problem, I need to transform the SOAP response from $ response = $ client -> __ getLastResponse (); And transform into a JSON object. Here is the image of the response I get in PHP with the above method.
stdClass return for $result:
stdClass Object ( [RealizarConsultaSQLResult] => AEC4 - AEC7 - )
Response SOAP:
<NewDataSet><Resultado> <CODTURMA>AEC4</CODTURMA><NOME>-</NOME></Resultado><Resultado><CODTURMA>AEC7</CODTURMA><NOME>-</NOME>
</Resultado></NewDataSet>
Observation: My code works normally, just need to receive the answer in the format below: (expected output):
{
"NewDataSet": {
"Resultado": [
{
"CODTURMA": "AEC4",
"NOME": "-"
},
{
"CODTURMA": "AEC7",
"NOME": "-"
}
]
}
}
My Code
<?php
require("wsdls.php");
//Cabeçalho de autenticação básica no SOAP
$soapParams = array('login' => $usuario,
'password' => base64_decode($pass),
'authentication' => SOAP_AUTHENTICATION_BASIC,
'trace' => 1,
'exceptions' => 0
);
$client = new SoapClient($WsdlRMSQL, $soapParams);
$params = array('codSentenca' => 'TOTVS.MDA.402', 'codColigada'=>'1', 'codSistema'=>'S','parameters'=>'CODCOLIGADA=1;CODFILIAL=1;IDPERLET=2;IDHABILITACAOFILIAL=10');
//Resultado do Webservice
$result = $client->realizarConsultaSQL($params);
//Resposta do SOAP
$response = $client->__getLastResponse();
//$xmlString = preg_replace("/(<\/?)(\w+):([^>]*>)/", "$1$2$3", $response);
//var_dump($response);
print_r($response);
?>
Image form SOAP response
try{
$xml = $client->__getLastResponse();
// SimpleXML seems to have problems with the colon ":" in the <xxx:yyy> response tags, so take them out
$xml = preg_replace("/(<\/?)(\w+):([^>]*>)/", "$1$2$3", $xml);
$xml = simplexml_load_string($xml);
$json = json_encode($xml);
$responseArray = json_decode($json,true);
// dd($responseArray['soapenvHeader']['headResponseHeader']['headStatusMessages']['headMessageDescription']);
Log::info("bill payment response".json_encode($result));
Log::info("bill payment response xml".$client->__getLastResponse());
if(!empty($responseArray['soapenvBody'])):
return redirect()->back()->with('status', $responseArray['soapenvHeader']['headResponseHeader']['headStatusMessages']['headMessageDescription']);
else:
return redirect()->back()->with('err', "We could not complete your request, please try again");
endif;
} catch (\SoapFault $fault) {
Log::info("bill payment error".json_encode($fault));
return redirect()->back()->with('err', $fault->getMessage());
}

PHP Soap Call Giving me Errors

Hi I'm trying to setup an api service with Limoanywhere system. But regardless of what I do I get invalid ApiKey & ApiID. I went into the back system and changed the ApiKey & ApiId multiple times but still no success.
Can anyone tell me if my code is correct?
<?php
$client = new SoapClient('https://qa.book.mylimobiz.com/api/ApiService.asmx?wsdl');
$options = array(
'ApiKey' => '***api key here****',
'ApiID' => '***api id here****'
);
$result = $client->__soapCall('Test', $options);
//var_dump($client->__getFunctions());
print_r($result);
?>
Here is the snippet from the service
http://qa.book.mylimobiz.com/api/ApiService.asmx?op=Test
Here is the result I get from when run my php code.
Array ( [TestResult] => Array ( [ResponseCode] => 1 [ResponseText] => Invalid ApiId or ApiKey ) )
Check this instead of test Test function not working giving error but test of the test all function are working.
<?php
$soapClient = new SoapClient("https://book.mylimobiz.com/api/ApiService.asmx?wsdl");
// Prepare SoapHeader parameters
$sh_param = array('apiId' => 'xxxxxx','apiKey' => 'xxxxxxxxxxxx');
$headers = new SoapHeader('https://book.mylimobiz.com/api/ApiService.asmx?wsdl', 'GetVehicleTypes', $sh_param);
// Prepare Soap Client
$trans = $soapClient->GetVehicleTypes($sh_param)->GetVehicleTypesResult;
echo "<pre>"; print_r($trans);
?>

SoapClient connection to SoapServer

I need to connect to a SOAP Server from php, I read a lot of documentation, examples and tutorials, but I still cannot make authentication to my server. I have done the work below:
$agencyNumber = 7818619810;
$fullTransmission = false;
//$context = array('header' => 'Content-type: application/soap+xml; charset=utf-8');
$params = array( 'agencyNumber' => 7818619810, 'fullTransmission' => 0/*,$context*/);
$client = new SoapClient("http://link/to/server?wsdl");
$test = $client->__getFunctions();
var_dump($test );// returns the functions my supplier provides, as well __getTypes() gives a bunch of variable arrays ect..
$response = $client->__soapCall('GetTransmissionTicket',array($params) );//line 16 which is mentioned on error print
var_dump($response);
Even though I set $context, when I try to run, I get the error below:
Fatal error: Uncaught SoapFault exception: [HTTP] Cannot process the
message because the content type 'text/xml; charset=utf-8' was not the
expected type 'application/soap+xml; charset=utf-8'. in
C:\xampp\htdocs\xml\inc\connection_test.php:16 Stack trace: #0
[internal function]: SoapClient->__doRequest('http://interfac...', '..//my-provider...', 1, 0) #1
C:..path..test.php(16): SoapClient->__soapCall('GetTransmission...',
Array) #2 {main} thrown in C:..path..test.php on line 16
The remote method I'm trying to call is called GetTransmissionTicket which takes two parameters, (int)agencyNumber and fullTransmission(bool)..
I want to emphasize that there are a lot of threads on this topic, some of which are really close to my question(1, 2, 3 and so on ..), but I really couldn't solve the problem. Please give a hand..
Kind Regards..
Try $params = array( 'agencyNumber' => 7818619810, 'fullTransmission' => false);
instead of $params = array( 'agencyNumber' => 7818619810, 'fullTransmission' => 0);
OR
Use $client = new SoapClient("http://link/to/server?wsdl", array('soap_version' => SOAP_1_1));
because
application/soap+xml is the content-type passed when using SOAP 1.2, text/xml is used with SOAP 1.1,
Reference : how to change content-type of request?
A simple example with soap and php can be
$url="your WSDL url";
$method = "Method you are calling";
$error=0;
$client = new SoapClient($url);
try
{
$info = $client->__call($method, array($param));
}
catch (SoapFault $fault)
{
$error = 1;
errorReport($fault->faultcode,$fault->faultstring);
die;
/*echo '<script type="text/javascript">alert("Sorry,App Returne the following ERROR:'.$fault->faultcode."-".$fault->faultstring.' We will now take you back to our homepage."); window.location = "'.$_SERVER['PHP_SELF'].'";</script> '; */
}
if($error==1)
{
$xml=$fault->faultstring;
}else{
$xml = $info;
}
return $xml;
Try implementing it and let me know. if it works for you.
Shouldn't the last line be var_dump($response); instead of var_dump($client);
Anyways, you can also try using this to get the result :
$response = $client->GetTransmissionTicket(array($params) );
var_dump($response);
I resolved this problem by switching from SOAP 1.2 to SOAP 1.1:
$this->client = new SoapClient(
$url,
array(
"trace" => TRUE,
"exception" => 0,
"soap_version" => SOAP_1_1,
"cache_wsdl" => WSDL_CACHE_MEMORY,
"local_cert" => 'mycert.pem',
)
);
I will answer my own question so that it helps someone one day. I used nusoap and changed the encoding to utf-8. The code snippet is below:
require_once "nusoap.php";
$client = new nusoap_client("http://interface.--Serivce-Supplier-Link/Service.svc?wsdl", "wsdl");
$client->soap_defencoding = 'UTF-8';
$result = $client->call("GetTransmissionTicket", array( 'agencyNumber' => 13155, 'fullTransmission' => false));
var_dump($result);
Kind Regards
may be little late but could help others. so here it goes:
$params is already an array so you don't have to use array($params) in
$response = $client->__soapCall('GetTransmissionTicket',array($params) );
instead use simple $params while calling.check it like this
$response = $client->GetTransmissionTicket($params);
also use $client->__getTypes(); to verify params to be passed.
use catch to good effect to trace faultstringand faultactor.
at the end if still not getting solution check it with soapUI(a software).

How to create PHP SOAP request with multiple namespaces

I'm attempting to get a shipping quote from an SOAP service. I've been able to successfully create authentication headers and query the SOAP service with basic requests that require no body parameters.
I'm able to create the proper structure for the request but the namespace values are not showing up in the request output.
Example code:
$client = new SoapClient("http://demo.smc3.com/AdminManager/services/RateWareXL?wsdl",
array('trace' => TRUE));
$headerParams = array('ns1:licenseKey' => $key,
'ns1:password' => $pass,
'ns1:username' => $user);
$soapStruct = new SoapVar($headerParams, SOAP_ENC_OBJECT);
$header = new SoapHeader($ns, 'AuthenticationToken', $soapStruct, false);
$client->__setSoapHeaders($header);
// Check if shipping is ready - base call
$ready_to_ship = $client->isReady();
The above works just fine and returns true if the shipping service is available.
So I use the following code to build the request body (only filling required fields):
I've also tried putting everything into an array and converting that to a SoapVar, I've tried including ns1: and ns2: in the body request creation but that hasn't worked either. I believe something needs to be adjusted in the request creation... not sure of the best approach..
$rate_request = $client->LTLRateShipment;
$rate_request->LTLRateShipmentRequest->destinationCountry = $destination_country;
$rate_request->LTLRateShipmentRequest->destinationPostalCode = $destination_postal_code;
$rate_request->LTLRateShipmentRequest->destinationPostalCode = $destination_postal_code;
$rate_request->LTLRateShipmentRequest->details->LTLRequestDetail->nmfcClass = $ship_class;
$rate_request->LTLRateShipmentRequest->details->LTLRequestDetail->weight = $ship_weight;
$rate_request->LTLRateShipmentRequest->originCountry = $origin_country;
$rate_request->LTLRateShipmentRequest->originPostalCode = $origin_postal_code;
$rate_request->LTLRateShipmentRequest->shipmentDateCCYYMMDD = $ship_date;
$rate_request->LTLRateShipmentRequest->tariffName = $tariff;
And it produces the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://webservices.smc.com">
<SOAP-ENV:Header>
<ns1:AuthenticationToken>
<ns1:licenseKey>xxxxxxxx</ns1:licenseKey>
<ns1:password>xxxxxxxx</ns1:password>
<ns1:username>xxxxxxxxm</ns1:username>
</ns1:AuthenticationToken>
</SOAP-ENV:Header>
<SOAP-ENV:Body>
<ns1:LTLRateShipment>
<LTLRateShipmentRequest>
<destinationCountry>USA</destinationCountry>
<destinationPostalCode>10001</destinationPostalCode>
<details>
<LTLRequestDetail>
<nmfcClass>60</nmfcClass>
<weight>300</weight>
</LTLRequestDetail>
</details>
<originCountry>USA</originCountry>
<originPostalCode>90210</originPostalCode>
<shipmentDateCCYYMMDD>20110516</shipmentDateCCYYMMDD>
<tariffName>DEMOLTLA</tariffName>
</LTLRateShipmentRequest>
</ns1:LTLRateShipment>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
But the output should include the namespaces (web: and web1: where appropriate). The above request returns an error code of missing tariffName.
Here's an example of what the xml request should look like:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:web="http://webservices.smc.com" xmlns:web1="http://web.ltl.smc.com">
<soapenv:Header>
<web:AuthenticationToken>
<web:licenseKey> string </web:licenseKey>
<web:password> string </web:password>
<web:username> string </web:username>
</web:AuthenticationToken>
</soapenv:Header>
<soapenv:Body>
<web:LTLRateShipment>
<web:LTLRateShipmentRequest>
<web1:LTL_Surcharge> string </web1:LTL_Surcharge>
<web1:TL_Surcharge> string </web1:TL_Surcharge>
<web1:destinationCity> string </web1:destinationCity>
<web1:destinationCountry> string </web1:destinationCountry>
<web1:destinationPostalCode> string </web1:destinationPostalCode>
<web1:destinationState> string </web1:destinationState>
<web1:details>
<!--Zero or more repetitions:-->
<web1:LTLRequestDetail>
<web1:nmfcClass> string </web1:nmfcClass>
<web1:weight> string </web1:weight>
</web1:LTLRequestDetail>
</web1:details>
<web1:discountApplication> string </web1:discountApplication>
<web1:mcDiscount> string </web1:mcDiscount>
<web1:orgDestToGateWayPointFlag> string </web1:orgDestToGateWayPointFlag>
<web1:originCity> string </web1:originCity>
<web1:originCountry> string </web1:originCountry>
<web1:originPostalCode> string </web1:originPostalCode>
<web1:originState> string </web1:originState>
<web1:rateAdjustmentFactor> string </web1:rateAdjustmentFactor>
<web1:shipmentDateCCYYMMDD> string </web1:shipmentDateCCYYMMDD>
<web1:shipmentID> string </web1:shipmentID>
<web1:stopAlternationWeight> string </web1:stopAlternationWeight>
<web1:surchargeApplication> string </web1:surchargeApplication>
<web1:tariffName> string </web1:tariffName>
<web1:weightBreak_Discount_1> string </web1:weightBreak_Discount_1>
</web:LTLRateShipmentRequest>
</web:LTLRateShipment>
</soapenv:Body>
</soapenv:Envelope>
Any suggestions / direction appreciated!
Ok... After too many hours of testing I finally have a solution..
I recreated the Authorization Token as a class and built the Soap Request without having to deal with any namespaces, SoapVars etc. it's surprisingly easy.
/* Object for holding authentication info
this could probably be accomplished using stdClass too */
class AuthHeader {
var $licenseKey;
var $password;
var $username;
function __construct($loginInfo) {
$this->licenseKey = $loginInfo['licenseKey'];
$this->password = $loginInfo['password'];
$this->username = $loginInfo['username'];
}
}
// set current soap header with login info
$client = new SoapClient("http://demo.smc3.com/AdminManager/services/RateWareXL?wsdl",
array('trace' => TRUE
));
// create header params array
$headerParams = array('licenseKey' => $key,
'password' => $pass,
'username' => $user);
// create AuthHeader object
$auth = new AuthHeader($headerParams);
// Turn auth header into a SOAP Header
$header = new SoapHeader($ns, 'AuthenticationToken', $auth, false);
// set the header
$client->__setSoapHeaders($header);
// Check if shipping is ready - base call
$ready_to_ship = $client->isReady();
// $last_request = $client->__getLastRequest();
$last_response = $client->__getLastResponse();
//print $last_request;
if ($last_response == true) {
print "Ready to ship\n";
// Create the shipping request
$d = new stdClass;
$d->nmfcClass = $ship_class;
$d->weight = $ship_weight;
$p = new stdClass;
$p->LTLRateShipmentRequest->destinationCountry = $destination_country;
$p->LTLRateShipmentRequest->destinationPostalCode = $destination_postal_code;
$p->LTLRateShipmentRequest->details = array($d);
$p->LTLRateShipmentRequest->originCountry = $origin_country;
$p->LTLRateShipmentRequest->originPostalCode = $origin_postal_code;
$p->LTLRateShipmentRequest->shipmentDateCCYYMMDD = $ship_date;
$p->LTLRateShipmentRequest->tariffName = $tariff;
$quote = $client->LTLRateShipment($p);
$last_request = $client->__getLastRequest();
$last_response = $client->__getLastResponse();
print "Request: " . $last_request;
print "\nResponse: " . $last_response;
}

Categories