PHP eBay Call Issues - php

Im trying to get the shipping info of a product, this is my code (I have hidden my app-id).
$endpoint2 = "http://open.api.ebay.com/shopping";
$xmlrequest2 = "<?xml version='1.0' encoding='utf-8'?>\n";
$xmlrequest2 .= "<GetShippingCostsRequest xmlns='urn:ebay:apis:eBLBaseComponents'>\n";
// $xmlrequest2 .= "<DestinationCountryCode>GB</DestinationCountryCode>\n";
// $xmlrequest2 .= "<IncludeDetails>true</IncludeDetails>\n";
$xmlrequest2 .= "<ItemID>".$id."</ItemID>\n";
$xmlrequest2 .= "</GetShippingCostsRequest>\n";
$session2 = curl_init($endpoint2); // create a curl session
curl_setopt($session2, CURLOPT_POST, true);
var_dump($xmlrequest2);
curl_setopt($session2, CURLOPT_POSTFIELDS, $xmlrequest2); // set the body of the POST
curl_setopt($session2, CURLOPT_RETURNTRANSFER, true);
$headers2 = array(
'X-EBAY-API-APP-ID:'.getsetting(2),
'X-EBAY-API-VERSION:849',
'X-EBAY-API-SITE-ID:3',
'X-EBAY-API-CALL-NAME:GetShippingCosts',
'X-EBAY-API-REQUEST-ENCODING:XML',
);
print_r($headers2);
// create a curl session
curl_setopt($session2, CURLOPT_HTTPHEADER, $headers2); //set headers using the above array of headers
$responseXML = curl_exec($session2);
// send the request
//echo $responseXML;
curl_close($session2);
return $responseXML;
And this is the output/errors i get.
string(162) "<?xml version='1.0' encoding='utf-8'?>
<GetShippingCostsRequest xmlns='urn:ebay:apis:eBLBaseComponents'>
<ItemID>300903657321</ItemID>
</GetShippingCostsRequest>
"
Array
(
[0] => X-EBAY-API-APP-ID:1234
[1] => X-EBAY-API-VERSION:849
[2] => X-EBAY-API-SITE-ID:3
[3] => X-EBAY-API-CALL-NAME:GetShippingCosts
[4] => X-EBAY-API-REQUEST-ENCODING:XML
)
<?xml version="1.0" encoding="UTF-8"?>
<GetShippingCostsResponse xmlns="">
<ns1:Ack xmlns:ns1="urn:ebay:apis:eBLBaseComponents">Failure</ns1:Ack>
<ns2:Errors xmlns:ns2="urn:ebay:apis:eBLBaseComponents">
<ns2:ShortMessage>Input data is invalid.</ns2:ShortMessage>
<ns2:LongMessage>Input data for the given tag is invalid or missing. Please check API documentation.</ns2:LongMessage>
<ns2:ErrorCode>1.22</ns2:ErrorCode>
<ns2:SeverityCode>Error</ns2:SeverityCode>
<ns2:ErrorParameters ParamID="0">
<ns2:Value>XML document structures must start and end within the same entity.</ns2:Value>
</ns2:ErrorParameters>
<ns2:ErrorClassification>RequestError</ns2:ErrorClassification>
</ns2:Errors>
<ns3:Build xmlns:ns3="urn:ebay:apis:eBLBaseComponents">E853_CORE_APILW_16579549_R1</ns3:Build>
<ns4:Version xmlns:ns4="urn:ebay:apis:eBLBaseComponents">853</ns4:Version>
</GetShippingCostsResponse>
Any ideas? I can't work out at all what the problem is. Nothing on their documentation seems to help. If i copy and paste the XML into their API Test Tool it works no problems.

I had the same problem with every call of eBay Shopping API. You can fix it adding Content-Type: text/xml;charset=UTF-8 to your headers (this fix the problem for me).

I don't see your credentials listed anywhere. The API tool they give you is a bit deceptive in that it wraps your calls for you with the credentials. http://developer.ebay.com/DevZone/guides/ebayfeatures/Basics/Call-StandardCallData.html#StandardOutputData
<?xml version="1.0" encoding="utf-8"?>
<GeteBayOfficialTimeRequest xmlns="urn:ebay:apis:eBLBaseComponents">
<RequesterCredentials>
<eBayAuthToken> Token goes here </eBayAuthToken>
</RequesterCredentials>
<Version>383</Version>
</GeteBayOfficialTimeRequest>

Related

remove soap headers from response before turning into simplexml object

I'm using Curl to execute a soap request.
Now it looks like there is a mistake returned in the headers that prevents me from turning the returned string into a simplexml object with the function simplexml_load_string. Below you can find the part of the response that fails in the simplexml function:
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><SOAP-ENV:Header><SOAP-SEC:Signature xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12"><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/><ds:Reference URI="#Body"><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>HV+/cOkUjNCdH5xuiLlGSHVgkUo=</ds:DigestValue></ds:Reference><ds:SignatureValue>MCwCFHXmoMrDUOScwMQ5g76OfxouICjBAhQtGKAorJLUQ0bA0UaKIe1gtmQPgA==</ds:SignatureValue></ds:SignedInfo></ds:Signature></SOAP-SEC:Signature></SOAP-ENV:Header><SOAP-ENV:Body xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12" SOAP-SEC:id="Body">
Is there a way to isolate the soap body content and parsing only that part with the simplexml_load_string?
Below the curl request:
$headers = array(
"Content-type: text/xml;charset=\"utf-8\"",
"Accept: text/xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"Content-length: ".strlen($xml_post_string),
);
$url = $soapUrl;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
$response = curl_exec($ch);
curl_close($ch);
$xml = simplexml_load_string(html_entity_decode($response), 'SimpleXMLElement', LIBXML_NOCDATA);
echo $xml->asXML();
if ($xml === false) {
echo "Failed to load XML: ";
foreach(libxml_get_errors() as $error) {
echo "<br>", $error->message;
}
} else {
var_dump($xml);
}
I don't have an answer for you right now, but you first need to separate curl from XML processing. You should start with logging your result from curl and making sure it is sane and what you expect. If it is, then move on to parsing it. curl should never break/change your data in any way, but the request itself (headers, etc.) might change the server's response.
Since I can't validate your server, I'm just going to go off of what you've provided. I've closed the <SOAP-ENV:Body> tag and converted the XML to readable, but otherwise it is untouched. This code parses the XML without a problem and then emits it exactly as expected.
$response = <<<'TAG'
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Header>
<SOAP-SEC:Signature xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1" />
<ds:Reference URI="#Body">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<ds:DigestValue>HV+/cOkUjNCdH5xuiLlGSHVgkUo=</ds:DigestValue>
</ds:Reference>
<ds:SignatureValue>MCwCFHXmoMrDUOScwMQ5g76OfxouICjBAhQtGKAorJLUQ0bA0UaKIe1gtmQPgA==</ds:SignatureValue>
</ds:SignedInfo>
</ds:Signature>
</SOAP-SEC:Signature>
</SOAP-ENV:Header>
<SOAP-ENV:Body xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12" SOAP-SEC:id="Body"></SOAP-ENV:Body>
</SOAP-ENV:Envelope>
TAG;
$xml = simplexml_load_string(html_entity_decode($response), 'SimpleXMLElement', LIBXML_NOCDATA);
echo '<pre>';
print_r(htmlspecialchars($xml->asXML()));
echo '</pre>';
The output is exactly the same as the input except it includes the XML directive and converts the body tag to self-closing:
<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SOAP-ENV:Header>
<SOAP-SEC:Signature xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12">
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/>
<ds:Reference URI="#Body">
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>HV+/cOkUjNCdH5xuiLlGSHVgkUo=</ds:DigestValue>
</ds:Reference>
<ds:SignatureValue>MCwCFHXmoMrDUOScwMQ5g76OfxouICjBAhQtGKAorJLUQ0bA0UaKIe1gtmQPgA==</ds:SignatureValue>
</ds:SignedInfo>
</ds:Signature>
</SOAP-SEC:Signature>
</SOAP-ENV:Header>
<SOAP-ENV:Body xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12" SOAP-SEC:id="Body"/>
</SOAP-ENV:Envelope>
So use this as a baseline. Write your curl response to a text file before doing anything else, and then read that text file back in and perform logic. Any transformation you apply to the string XML should also be logged and compared to make sure it is doing what you expected. On production you'd skip that but this just helps during the debugging.
Also, I'm not really sure what the point of html_entity_decode is in this. If you are receiving XML (as your request mime type specifies) then it shouldn't have any escape sequences applied to it, but maybe you have an exceptional case, too.
Just to give some example XML content, this will vary for any file but just shows how you can access the data...
<SOAP-ENV:Body
xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12"
SOAP-SEC:id="Body">
<BodyContent>SomeData</BodyContent>
<OtherContent>2</OtherContent>
</SOAP-ENV:Body>
Then it would be a case of using XPath to find the <SOAP-ENV:Body> tag
$xml->registerXPathNamespace("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
$bodyBlock = $xml->xpath("//SOAP-ENV:Body")[0];
(note that as xpath() returns a list of matches, using [0] just uses the first one).
This next part depends on the message being processed, but as the example I gave has child elements with no namespace prefix, then you can extract these using ->children() and this eases access to the contents. The main part is that at this point the $bodyBlock contains this...
<SOAP-ENV:Body xmlns:SOAP-SEC="http://schemas.xmlsoap.org/soap/security/2000-12" SOAP-SEC:id="Body">
<BodyContent>SomeData</BodyContent>
<OtherContent>2</OtherContent>
</SOAP-ENV:Body>
So to put that together in your original code...
$xml = simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA);
if ($xml === false) {
echo "Failed to load XML: ";
foreach(libxml_get_errors() as $error) {
echo "<br>", $error->message;
}
} else {
// Search for the Body element (this is in the SOAP-ENV namespace)
$xml->registerXPathNamespace("SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/");
$bodyBlock = $xml->xpath("//SOAP-ENV:Body")[0];
// If the content does not have a namespace, extract the children from the default namespace
$body = $bodyBlock->children();
// You can now access the content.
echo $body->BodyContent.PHP_EOL;
echo $body->OtherContent;
}
which outputs the two values in the body....
SomeData
2

Parsing SOAP response with SimpleXML

I am trying to call a soap server method. Everything works fine except one thing. I get a respone from the server in XML format. So far so good. But the problem is that i need to get the values of the XML and normally i do that just with a foreach and get the values i need. But this time the name of the child i need to get data from is called: 'return'. So i can not reference to that in a foreach function.
Could someone tell me how i can reach the same result but with a different way?
My answer from the server:
<soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:body>
<ns2:getauthresponse xmlns:ns2="http://dpd.com/common/service/types/LoginService/2.0" xmlns:ns3="http://dpd.com/common/service/exceptions">
<return>
<delisid>thedelisid</delisid>
<customeruid>thecustomerid</customeruid>
<authtoken>theauthenticationcode</authtoken>
<depot>thedepot</depot>
</return>
</ns2:getauthresponse>
</soap:body>
</soap:envelope>
the code i would normally use to get the result:
foreach($xml->return->authtoken as $authtoken)
{
print_r($authtoken);
}
The problem is the return sign here, php keeps seeing it as the return statement.
I also made it an array using new SimpleXMLElement.
And the error i get when i run the code is:
Invalid argument supplied for foreach()
How can i get the value of authtoken?
All the code:
$xml_getAuth = '
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:ns="http://dpd.com/common/service/types/LoginService/2.0">
<soapenv:Header/>
<soapenv:Body>
<ns:getAuth>
<delisId>'.$delisId.'</delisId>
<password>'.$password.'</password>
<messageLanguage>'.$messageLanguage.'</messageLanguage>
</ns:getAuth>
</soapenv:Body>
<soapenv:Envelope>
';
$headers_getAuth = array(
"POST HTTP/1.1",
"Content-type: application/soap+xml; charset=\"utf-8\"",
"SOAPAction: \"http://dpd.com/common/service/LoginService/2.0/getAuth\"",
"Content-length: ".strlen($xml_getAuth)
);
$getAuth = curl_init('https://public-ws-stage.dpd.com/services/LoginService/V2_0/');
curl_setopt($getAuth, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($getAuth, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($getAuth, CURLOPT_POST, 1);
curl_setopt($getAuth, CURLOPT_HTTPHEADER, $headers_getAuth);
curl_setopt($getAuth, CURLOPT_POSTFIELDS, "$xml_getAuth");
curl_setopt($getAuth, CURLOPT_RETURNTRANSFER, 1);
$output_getAuth = curl_exec($getAuth);
//Gebruikernsaam en wachtwoord komen niet overeen
if(strpos($output_getAuth,'LOGIN_8') !== false)
{
echo "Verkeerde gebruikernsaam of wachtwoord, neem contact op met uw systeembeheerder voor meer informatie.";
exit;
}
$xml = new SimpleXMLElement($output_getAuth);
foreach($xml->return->authtoken as $authtoken)
{
print_r($authtoken);
}
Answer from the soap call:
stdClass Object ( [return] => stdClass Object ( [delisId] => delisid [customerUid] => custid [authToken] => authtoken [depot] => depot ) )
First of all, you should probably be using SoapClient instead of SimpleXML. For example:
$c = new SoapClient('https://public-ws-stage.dpd.com/services/LoginService/V2_0/?WSDL');
$res = $c->getAuth(array(
'delisId' => 'foo',
'password' => 'bar',
'messageLanguage' => 'en-us',
));
echo $res->result->authToken;
That said, using xpath solves many problems:
<?php
$response = <<<XML
<soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:body>
<ns2:getauthresponse xmlns:ns2="http://dpd.com/common/service/types/LoginService/2.0" xmlns:ns3="http://dpd.com/common/service/exceptions">
<return>
<delisid>thedelisid</delisid>
<customeruid>thecustomerid</customeruid>
<authtoken>theauthenticationcode</authtoken>
<depot>thedepot</depot>
</return>
</ns2:getauthresponse>
</soap:body>
</soap:envelope>
XML;
$xml = simplexml_load_string($response);
foreach ($xml->xpath('//return') as $tmp) {
echo "authtoken = ", $tmp->authtoken, PHP_EOL;
}

PHP sending XML with soap returns unknown rerror

I'm trying to send user registrations with soap to another server. I'm creating an xml with DOMdocument and than after saveXML I'm running the soap which should return an xml with registration id plus all the data I sent in my xml.
But the Soap returns unknown error. exactly this: stdClass Object ( [RegisztracioInsResult] => stdClass Object ( [any] => 5Unknown error ) )
and this is how I send my xml.
/*xml creation with DOMdocument*/
$xml = saveXML();
$url = 'http://mx.biopont.com/services/Vision.asmx?wsdl';
$trace = '1';
$client = new SoapClient($url, array('trace' => $trace, "exceptions" => 0, 'features' => SOAP_SINGLE_ELEMENT_ARRAYS));
$params = $client->RegisztracioIns(array('xml' => $xml));
$print_r($params);
If I click on the description of the RegisztracioIns service at this URL http://mx.biopont.com/services/Vision.asmx it shows me this:
POST /services/Vision.asmx HTTP/1.1
Host: mx.biopont.com
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://mx.biopont.com/services/RegisztracioIns"
<?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>
<RegisztracioIns xmlns="http://mx.biopont.com/services/">
<xml>string</xml>
</RegisztracioIns>
</soap:Body>
</soap:Envelope>
According to this I think I'm doing the upload correctly but maybe not I don't have much experience with soap.
Is there anything I'm missing? I also tried to save the xml to my server an than get the contents with file_get_contents(). but the result was the same.
You should be able to do something like this:
$res = $client->__soapCall( 'RegisztracioIns', array('xml'=>'my string to send'));
To have the wsdl wrap 'my string to send' in the proper tags.
You are doing something similar, but I dont think the wsdl is actually wrapping the string you are trying to pass, and passing nothing instead, resulting in unknown error.
You can examine the outgoing xml using $client->__getLastRequest();.
(Also, you have a small typo in your code on the last line should be print_r($params);.)
Failing that you could try to write the xml yourself using SoapVar() and setting the type to XSD_ANYXML.
It seems cleaner to me when the wsdl wraps everything for you, but its better than banging your head against the wall until it does.
I made an attempt to do just that with your wsdl. Give this a try:
$wsdl = "http://mx.biopont.com/services/Vision.asmx?wsdl";
$client = new SoapClient($wsdl, array( 'soap_version' => SOAP_1_1,
'trace' => true,
));
try {
$xml = "<RegisztracioIns xmlns='http://mx.biopont.com/services/'>
<xml>string</xml>
</RegisztracioIns>";
$args= array(new SoapVar($xml, XSD_ANYXML));
$res = $client->__soapCall( 'RegisztracioIns', $args );
var_dump($res);
} catch (SoapFault $e) {
echo "Error: {$e}";
}
print_r($client->__getLastRequest());
print_r($client->__getLastResponse());
I can't exactly read the response I am getting with that given that it is Hungarian (I think?). So let me know if that works for you.

Send XML with php via post

I know there are any number of similar questions to this on SO, but I've tried messing around with all the solutions and haven't seemed to be able to make it work. I am trying to post xml directly to a web service and get a response back. Technically I am trying to connect to freightquote.com, the documentation for which you can find in the upper right hand corner of this page under documentation. I only mention that because I see the term SOAP a lot in their xml and it might make a difference. Anyway what I want is the ability to send xml to some url and get a response back.
So if I had the following
$xml = "<?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:Body>
<GetRatingEngineQuote xmlns='http://tempuri.org/'>
<request>
<CustomerId>0</CustomerId> <!-- Identifier for customer provided by Freightquote -->
<QuoteType>B2B</QuoteType> <!-- B2B / eBay /Freightview -->
<ServiceType>LTL</ServiceType> <!-- LTL / Truckload / Groupage / Haulage / Al -->
<QuoteShipment>
<IsBlind>false</IsBlind>
<PickupDate>2010-09-13T00:00:00</PickupDate>
<SortAndSegregate>false</SortAndSegregate>
<ShipmentLocations>
<Location>
<LocationType>Origin</LocationType>
<RequiresArrivalNotification>false</RequiresArrivalNotification>
<HasDeliveryAppointment>false</HasDeliveryAppointment>
<IsLimitedAccess>false</IsLimitedAccess>
<HasLoadingDock>false</HasLoadingDock>
<IsConstructionSite>false</IsConstructionSite>
<RequiresInsideDelivery>false</RequiresInsideDelivery>
<IsTradeShow>false</IsTradeShow>
<IsResidential>false</IsResidential>
<RequiresLiftgate>false</RequiresLiftgate>
<LocationAddress>
<PostalCode>30303</PostalCode>
<CountryCode>US</CountryCode>
</LocationAddress>
<AdditionalServices />
</Location>
<Location>
<LocationType>Destination</LocationType>
<RequiresArrivalNotification>false</RequiresArrivalNotification>
<HasDeliveryAppointment>false</HasDeliveryAppointment>
<IsLimitedAccess>false</IsLimitedAccess>
<HasLoadingDock>false</HasLoadingDock>
<IsConstructionSite>false</IsConstructionSite>
<RequiresInsideDelivery>false</RequiresInsideDelivery>
<IsTradeShow>false</IsTradeShow>
<IsResidential>false</IsResidential>
<RequiresLiftgate>false</RequiresLiftgate>
<LocationAddress>
<PostalCode>60606</PostalCode>
<CountryCode>US</CountryCode>
</LocationAddress>
<AdditionalServices />
</Location>
</ShipmentLocations>
<ShipmentProducts>
<Product>
<Class>55</Class>
<Weight>1200</Weight>
<Length>0</Length>
<Width>0</Width>
<Height>0</Height>
<ProductDescription>Books</ProductDescription>
<PackageType>Pallets_48x48</PackageType>
<IsStackable>false</IsStackable>
<DeclaredValue>0</DeclaredValue>
<CommodityType>GeneralMerchandise</CommodityType>
<ContentType>NewCommercialGoods</ContentType>
<IsHazardousMaterial>false</IsHazardousMaterial>
<PieceCount>5</PieceCount>
<ItemNumber>0</ItemNumber>
</Product>
</ShipmentProducts>
<ShipmentContacts />
</QuoteShipment>
</request>
<user>
<Name>someone#something.com</Name>
<Password>password</Password>
</user>
</GetRatingEngineQuote>
</soap:Body>
</soap:Envelope>";
(I edited this to contain my actual xml since it may lend some perspective
I'd want to send it to http://www.someexample.com and get a response. Also, do I need to encode it? I've done a lot of sending xml back and forth with android, and never had to but that might be part of my problem.
My attempt to send the information currently looks like this
$xml_post_string = 'XML='.urlencode($xml->asXML());
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://b2b.Freightquote.com/WebService/QuoteService.asmx');
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);
If you are walking around SOAP services, I strongly recommend you to learn basics once, and then use this great tool again and again. There are many features you can just use, or you will be reinventing the wheel and struggling with generating xml files, parsing xml files, faults etc. Use prepared tools and your life will be easier and your code better (less bugs).
Look at http://www.php.net/manual/en/soapclient.soapcall.php#example-5266 how to consume SOAP webservice. It is not so hard to understand.
Here is some code how you can analyze webserivce. Then map types to classes and just send and receive php objects. You can look for some tool to generate classes automatically (http://www.urdalen.no/wsdl2php/manual.php).
<?php
try
{
$client = new SoapClient('http://b2b.freightquote.com/WebService/QuoteService.asmx?WSDL');
// read function list
$funcstions = $client->__getFunctions();
var_dump($funcstions);
// read some request obejct
$response = $client->__getTypes();
var_dump($response);
}
catch (SoapFault $e)
{
// do some service level error stuff
}
catch (Exception $e)
{
// do some application level error stuff
}
If you will use wsdl2php generating tool, everything is very easy:
<?php
require_once('./QuoteService.php');
try
{
$client = new QuoteService();
// create request
$tracking = new TrackingRequest();
$tracking->BOLNumber = 67635735;
$request = new GetTrackingInformation();
$request->request = $tracking;
// send request
$response = $client->GetTrackingInformation($request);
var_dump($response);
}
catch (SoapFault $e)
{
// do some service level error stuff
echo 'Soap fault ' . $e->getMessage();
}
catch (Exception $e)
{
// do some application level error stuff
echo 'Error ' . $e->getMessage();
}
Generated php code for QuoteService.php you can see here: http://pastie.org/8165331
This is captured communication:
Request
POST /WebService/QuoteService.asmx HTTP/1.1
Host: b2b.freightquote.com
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.4.17
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://tempuri.org/GetTrackingInformation"
Content-Length: 324
<?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:GetTrackingInformation>
<ns1:request>
<ns1:BOLNumber>67635735</ns1:BOLNumber>
</ns1:request>
</ns1:GetTrackingInformation>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Response
HTTP/1.1 200 OK
Date: Mon, 22 Jul 2013 21:46:06 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Content-Length: 660
Set-Cookie: BIGipServerb2b_freightquote_com=570501130.20480.0000; path=/
<?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:Body>
<GetTrackingInformationResponse xmlns="http://tempuri.org/">
<GetTrackingInformationResult>
<BOLNumber>0</BOLNumber>
<EstimatedDelivery>0001-01-01T00:00:00</EstimatedDelivery>
<TrackingLogs />
<ValidationErrors>
<B2BError>
<ErrorType>Validation</ErrorType>
<ErrorMessage>Unable to find shipment with BOL 67635735.</ErrorMessage>
</B2BError>
</ValidationErrors>
</GetTrackingInformationResult>
</GetTrackingInformationResponse>
</soap:Body>
</soap:Envelope>
First, if your code is written like this, I doubt this works be cause of the quotes...
You should use double quote around your xml:
$my_xml = "<?xml version='1.0' standalone='yes'?>
<user>
<Name>xmltest#freightquote.com</Name>
<Password>XML</Password>
</user>";
Also, you could use poster, a firefox addon (there is probably the equivalent on chrome), to help you with your requests, especially if you use WebServices. That way, you will be able to see if the error is server-side or client-side.
This should help you debugging.
I use this command-line script to test SOAP call:
#!/usr/bin/php
<?php
//file client-test.php
$xml_data = file_get_contents('php://stdin');
$ch = curl_init('http://example.com/server/');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('SOAPAction', 'MySoapAction'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
print_r($output);
Usage like this (in command line) :
$ client-test.php < yourSoapEnveloppe.xml
In this example the yourSoapEnveloppe.xml file is the content of your $xml variable.
You can use stream_context_create and file_get_contents to send xml in post.
$xml = "<your_xml_string>";
$send_context = stream_context_create(array(
'http' => array(
'method' => 'POST',
'header' => 'Content-Type: application/xml',
'content' => $xml
)
));
print file_get_contents($url, false, $send_context);

SOAP API call with PHP

I have been working on this for a week now and have trouble executing this code. I want to retrieve data via SOAP and work with it in PHP. My trouble is, that I am having trouble sending the 'RequesterCredentials'.
I will show the XML code so you all can see the information I am trying to send, and then the PHP code I am using.
XML sample code
POST /AuctionService.asmx HTTP/1.1
Host: apiv2.gunbroker.com
Content-Type: text/xml; charset=utf-8
Content-Length: 200
SOAPAction: "GunBrokerAPI_V2/GetItem"
<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>
<RequesterCredentials xmlns="GunBrokerAPI_V2">
<DevKey>devkey</DevKey>
<AppKey>appkey</AppKey>
</RequesterCredentials>
</soap:Header>
<soap:Body>
<GetItem xmlns="GunBrokerAPI_V2">
<GetItemRequest>
<ItemID>312007942</ItemID>
<ItemDetail>Std</ItemDetail>
</GetItemRequest>
</GetItem>
</soap:Body>
</soap:Envelope>
PHP code that I am using to make the call
$client = new SoapClient("http://apiv2.gunbroker.com/AuctionService.asmx?WSDL");
$appkey = 'XXXXXX-XXXXXX-XXXXXX';
$devkey = 'XXXXXX-XXXXXX-XXXXXX';
$header = new SoapHeader('GunBrokerAPI_V2', 'RequesterCredentials', array('DevKey' => $devkey, 'AppKey' => $appkey), 0);
$client->__setSoapHeaders(array($header));
$result = $client->GetItem('312343077');
echo '<pre>', print_r($result, true), '</pre>';
The result I get
stdClass Object
(
[GetItemResult] => stdClass Object
(
[Timestamp] => 2012-11-07T18:17:31.9032903-05:00
[Ack] => Failure
[Errors] => stdClass Object
(
[ShortMessage] => GunBrokerAPI_V2 Error Message : [GetItem]
// You must fill in the 'RequesterCredentialsValue'
// SOAP header for this Web Service method.
[ErrorCode] => 1
)
// The rest if just an array of empty fields that
// I could retrieve if I wasn’t having problems.
I’m not sure if the problem is the way I’m sending the SoapHeaders or if I am misunderstanding the syntax. How can I fix it?
Use an object instead of an associative array for headers:
$obj = new stdClass();
$obj->AppKey = $appkey;
$obj->DevKey = $devkey;
$header = new SoapHeader('GunBrokerAPI_V2', 'RequesterCredentials', $obj, 0);
And the next problem you might face will be at the GetItem call. You also need an object, wrapped in an associative array:
$item = new stdClass;
$item->ItemID = '312343077';
$item->ItemDetail = 'Std';
$result = $client->GetItem(array('GetItemRequest' => $item));

Categories