I am trying to call a SOAP API using PHP and have been given the following example CURL call:
curl --location --request POST 'https://soapurl.test/mysoapcall'
--header 'Content-Type: application/xml'
--header 'client-id: <<your client id>>'
--header 'client-secret: <<your client secret>>'
--header 'Authorization: Bearer <<token>>'
--data-raw '<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header></env:Header>
<S:Body>
<ns0:getReturnedValues xmlns:ns0="https://soapurl.test/anotherurl1" xmlns:ns1="https://soapurl.test/anotherurl2">
<ns0:var1>100</ns0:var1>
<ns0:var2>XXX</ns0:var2>
</ns0:getReturnedValues>
</S:Body>
</S:Envelope>'
I can successfully call the above via Postman, but when I am writing the PHP code using SoapClient, I keep getting "One or more required API parameters are missing in the API request."
I know that I must have something wrong with how I am defining the SOAP headers or how I am defining the uri, but I can't work out what it is.
Here is my PHP code:
$client = new SoapClient(null, array('location' => "https://soapurl.test/mysoapcall",
'uri' => "https://soapurl.test/anotherurl1");
$ns = 'https://soapurl.test/anotherurl1';
$headers = array();
$headers[] = new SoapHeader($ns,
'client-id',
'my_client_id');
$headers[] = new SoapHeader($ns,
'client-secret',
'my_client_secret');
$headers[] = new SoapHeader($ns,
'Authorization',
'Bearer my_bearer_token');
$client->__setSoapHeaders($headers);
$client->__soapCall("getReturnedValues", array('var1'=>'100', 'var2' => 'XXX'));
$client->__soapCall("getReturnedValues", [
new \SoapParam('100', 'var1'),
new \SoapParam('XXX', 'var2')
]);
My PHP code generates the following request:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:enc="http://www.w3.org/2003/05/soap-encoding" xmlns:ns1="https://soapurl.test/anotherurl1" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<env:Body>
<ns1:getReturnedValues env:encodingStyle="http://www.w3.org/2003/05/soap-encoding">
<var1 xsi:type="xsd:string">100</var1>
<var2 xsi:type="xsd:string">XXX</var2>
</ns1:getReturnedValues>
</env:Body>
</env:Envelope>
Which is obviously not the same as the example I was supplied with.
I'm new to SOAP, so please can someone advise on what I am doing wrong? Many thanks
Related
im trying to make a xml request to a ws using guzzle,(and i try with curl to) in php but always the response its in plain text no in xml
$client = new \GuzzleHttp\Client(['verify' => false]);
$soapRequest = <<<XML
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:tem="http://tempuri.org/" xmlns:san="mywebsservice">
<soap:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
<wsa:Action>http://tempuri.org/mywebsservice</wsa:Action>
<To soap:mustUnderstand="1" xmlns="http://www.w3.org/2005/08/addressing">mywebsservice </To>
</soap:Header>
<soap:Body>
<tem:GetSecurityToken>
<tem:request>
<san:Connection>mywebsservice</san:Connection>
<san:Passwoord>mywebsservice</san:Passwoord>
<san:System>mywebsservice</san:System>
<san:UserName>mywebsservice</san:UserName>
</tem:request>
</tem:GetSecurityToken>
</soap:Body>
</soap:Envelope>
XML;
$request = $client->request('POST','mywebsservice', [
'headers' => [
'Content-Type' => 'application/soap+xml'
],
'body' => $soapRequest
]);
$response = $request->getBody()->getContents();
var_dump($response);
this is the response
this is the response
string(1870) "
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://tempuri.org/webservices/GetSecurityTokenResponse</a:Action>
<ActivityId CorrelationId="cf1c12da-af1b-4013-ba89-25db2fa67dc1" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">00000000-0000-0000-0000-000000000000</ActivityId>
</s:Header>
<s:Body>
<GetSecurityTokenResponse xmlns="http://tempuri.org/">
<GetSecurityTokenResult xmlns:b="webservices" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<b:AccessToken>token access</b:AccessToken>
<b:IdToken>the token</b:IdToken>
<b:TokenType>Bearer</b:TokenType>
</GetSecurityTokenResult>
</GetSecurityTokenResponse>
</s:Body>
</s:Envelope>
"
The headers you are sending is what the receiving server uses to decide what content to serve. It will still be text content though, but only with a different Content-Type header.
guzzlehttp/guzzle 6.x
The $response->json() and $response->xml() helpers were removed in 6.x. The following lines can be used to replicate that behaviour:
// Get an associative array from a JSON response.
$data = json_decode($response->getBody(), true);
See https://www.php.net/manual/en/function.json-decode.php
// Get a `SimpleXMLElement` object from an XML response.
$xml = simplexml_load_string($response->getBody());
See https://www.php.net/manual/en/function.simplexml-load-string.php
guzzlehttp/guzzle 5.x
Guzzle 5.x has some shortcuts to help you out:
$client = new Client(['base_uri' => 'https://example.com']);
$response = $client->get('/');
// $response = Psr\Http\Message\ResponseInterface
$body = (string) $response->getBody();
// $body = raw request contents in string format.
// If you dont cast `(string)`, you'll get a Stream object which is another story.
Now whatever you do with $body is up to you. If it is a JSON response, you'd do:
$data = $response->json();
If it is XML, you can call:
$xml = $response->xml();
I never work with XML APIs so i can't give you any more examples on how to traverse the XML you will retrieve.
I'm using PHP SoapClient, and am running into an issue with getting the request format just as a third party wants it.
They want it like this:
POST /service.asmx HTTP/1.1
Host: service.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>
<Order xmlns="http://someservice">
<json>string</json>
</Order>
</soap12:Body>
</soap12:Envelope>
However, the closest I can seem to get it, using SoapClient, is like this:
POST /service.asmx HTTP/1.1
Host: service.com
Content-Type: application/soap+xml; charset=utf-8; action="http://someservice"
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>
<Order>
<json>string</json>
</Order>
</soap12:Body>
</soap12:Envelope>
Notice how the action in my request is in the http header, and the action in their ideal format is in the Order tag. The thing is, it's SoapClient that is generating where that action is being placed - it gets that specific url from the WSDL, it's not even in my code.
How do I tell SoapClient to put it in the right spot? For my part, trying to only include what's necessary, this is essentially the code:
$this->client = new SoapClient($this->wsdl, array(
'soap_version' => SOAP_1_2,
'encoding' => 'UTF-8',
'stream_context' => stream_context_create($context),
'trace' => true,
'exceptions' => true,
)
);
$json = json_encode($request);
// Prepare the xml
$xml = array();
$xml[] = new SoapVar($json, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema', 'json');
$this->finalXML = new SoapVar($xml, SOAP_ENC_OBJECT, null, null, 'Order');
$this->response = $this->client->CreateOrder($this->finalXML);
After days of banging my head, I found this and ended up making the accepted, hacky solution work for me:
Change SOAP request format
Apparently, when you're working with a poorly written Soap API, there's not a lot you can do.
I need to make soap calls which include headers like this:
<soap:Header>
<Agency xmlns="http://schemas.costacrociere.com/WebAffiliation">
<Code>1111</Code>
<Culture />
</Agency>
<Partner xmlns="http://schemas.costacrociere.com/WebAffiliation">
<Name>AAAA</Name>
<Password>XXXX</Password>
</Partner>
</soap:Header>
How to do that in PHP using SoapClient?
Plz help :)
I did it:
$ns="http://schemas.costacrociere.com/WebAffiliation";
//Body of the Soap Header.
$headerbody1 = array("Name" => "AAAA", "Password" => "XXXX");
$headerbody2 = array("Code" => "1111");
//Create Soap Header.
$header[] = new SOAPHeader($ns, 'Partner', $headerbody1);
$header[] = new SOAPHeader($ns, 'Agency', $headerbody2);
//set the Headers of Soap Client.
$client->__setSoapHeaders($header);
It's my first time with SOAP, I already read all manuals and still stacked with the following example:
<?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:Header>
<AuthenticationInfo xmlns="https://blabla.com/ws/Quoting">
<strUserName>[username]</strUserName>
<strPassword>[password]</strPassword>
</AuthenticationInfo>
</soap:Header>
<soap:Body>
<GetQuotes xmlns="https://blabla.com/ws/Quoting">
<CallerClientID>0</CallerClientID>
<quoteRequest>
<CapacityCode>2</CapacityCode>
<BabiesCount>0</BabiesCount>
<QuotingOptions>0</QuotingOptions>
</quoteRequest>
<clientIDs>
<int>20295</int>
</clientIDs>
<withUrlParam>false</withUrlParam>
</GetQuotes>
</soap:Body>
</soap:Envelope>
I do not understand how to start the soapclient with authorization, please help.
You need to use SoapHeader. Below is the example.
$ns = 'https://blabla.com/ws/Quoting'; //Namespace of the WS.
//Body of the Soap Header.
$headerbody = array('strUserName' => $someUser,
'strPassword' => $somePass);
//Create Soap Header.
$header = new SOAPHeader($ns, 'AuthenticationInfo', $headerbody);
//set the Headers of Soap Client.
$soap_client->__setSoapHeaders($header);
This is my first time with web services/SOAP...i have been trying to consume .Net web services using PHP but to no avail. I have searched and read all pages that google throws up for anything related to this but i am still lost.
The thing is the SOAP service i am trying to call has an authorization header and i can't figure out a way to authenticate my request.
I have tried the php-soapclient and NuSoap both but there is no sample code available that would help. So any help would be great.
The following is a sample SOAP 1.1 request and response.
POST /OxiWalletService/Service.asmx HTTP/1.1
Host: 172.160.0.49
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/WS_GetData"
<?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>
<AuthHeader xmlns="http://tempuri.org/">
<UserName>string</UserName>
<Password>string</Password>
</AuthHeader>
</soap:Header>
<soap:Body>
<WS_GetData xmlns="http://tempuri.org/">
<xmlString>string</xmlString>
</WS_GetData>
</soap:Body>
</soap:Envelope>
Response
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?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:Body>
<WS_GetDataResponse xmlns="http://tempuri.org/">
<WS_GetDataResult>string</WS_GetDataResult>
</WS_GetDataResponse>
</soap:Body>
</soap:Envelope>
Can anybody please gimme a sample code on how to consume such a service.
Many thanks in advance!
This is the code that i have used to call the web service
<?php
$soap_client = new SoapClient("http://172.160.0.49/OxiWalletService/Service.asmx?WSDL");
$Uid='oxigen';
$Pwd='oxigen';
$ns = "http://tempuri.org/";
//Body of the Soap Header.
$headerbody = array('UserName' => $Uid,
'Password' => $Pwd
);
//Create Soap Header.
$header = new SOAPHeader($ns, 'AuthHeader', $headerbody);
//set the Headers of Soap Client.
$soap_client->__setSoapHeaders($header);
$par="<Wallet><SPName>AuthenticateMerchantWebVending</SPName><Parameters><Parameter><Name>#Account</Name><Size>50</Size><Value>1135600016</Value><Type>varchar</Type></Parameter><Parameter><Name>#Password</Name><Size>20</Size><Value>0OgknrdonyM=</Value><Type>varchar</Type></Parameter></Parameters><ParameterCount>2</ParameterCount><DataBase>1</DataBase></Wallet>";
$param=array('xmlString'=>$par);
$result=$soap_client->__SoapCall('WS_GetData',$param);
print_r ($result);
?>
and i am getting the following as output:
stdClass Object ( [WS_GetDataResult] => 2Unknown Error )
Ideas??
So it turns out you've to pass the second argument with parameters as the key of the array
meaning this
$result=$soap_client->__SoapCall('WS_GetData',$param);
should be
$result=$soap_client->__SoapCall('WS_GetData',array('parameters'=>$param));
This works now.
I think this should do the trick:
www.php.net/manual/en/soapclient.setsoapheaders.php
$ns = "http://tempuri.org/"
//Body of the Soap Header.
$headerbody = array('UserName' => $yourUsername,
'Password' => $yourPassword,
);
//Create Soap Header.
$header = new SOAPHeader($ns, 'AuthHeader', $headerbody);
//set the Headers of Soap Client.
$soap_client->__setSoapHeaders($header);