I'm having problems submitting a feed to Amazon MWS. I keep receiving the following error: "Invalid query string provided - Keys may not contain <"
This is my code:
$apicall = $this->build_url($function, $params);
$ch = curl_init($apicall);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLINFO_HEADER_OUT, true);
if ($this->xml) {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, (string)$this->xml);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: text/xml"));
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-MD5: " . base64_encode(md5($this->xml))));
}
else {
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: text/xml'));
}
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
$response = curl_exec($ch);
$info = print_r(curl_getinfo($ch), true);
curl_close($ch);
$apicall is formed on-the-fly and comes in the form:
https://mws.amazonservices.com/Feeds/2009-01-01?ASINList.ASIN.1=B00C5XBAOA&AWSAccessKeyId=***&Action=SubmitFeed&FeedType=_POST_PRODUCT_PRICING_DATA_&MWSAuthToken=***&SellerId=***&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2015-06-09T09%3A58%3A01.000Z&Version=2009-01-01&Signature=***
(which works fine with other calls to Reports or to Orders)
$this->xml is kept as a "TEXT" field in the MySQL db; this is a sample XML (I added lines to make it readable):
<?xml version="1.0"?>
<AmazonEnvelope xsi="http://www.w3.org/2001/XMLSchema-instance" noNamespaceSchemaLocation="amzn-envelope.xsd">
<Header>
<DocumentVersion>1.01</DocumentVersion>
<MerchantIdentifier>***</MerchantIdentifier>
</Header>
<MessageType>Price</MessageType>
<Message>
<MessageID>1</MessageID>
<OperationType>Update</OperationType>
<Price>
<SKU>***</SKU>
<StandardPrice currency="USD">33.5</StandardPrice>
</Price>
</Message>
</AmazonEnvelope>
I seem to review every single relevant link on the internet and cannot find the answer.
Maybe someone can give me a hint what may go wrong in the above code?
Thanks.
Found the solutions myself (after digging more that a day):
1) Content-MD5 must be calculated in the following way:
base64_encode(md5($this->xml, **true**));
(thanks to this answer: https://sellercentral.amazon.com/forums/message.jspa?messageID=2767745)
2) passing header parameters to cUrl must be one-time operation, that is - all headers have to be passed as an array.
Related
Edit
The code given below will work in localhost as it is, if anyone want to copy and try it.The given credentials are valid.
I have a php code which requests data from an API service. An XML request is sent and in response XML data is recieved. I have stored the respose data in a variable $output. When doing echo $output, the details in the XML response is printed. But now I need to parse this response and store the required data in variables. E.g: I need to save $customer_id = value from the <customer_id>12345</customer_id>. I did a thorough google search and tried all the snippets provided by different developers, but no use.
I tried var_dump(simplexml_load_string($output)); and it is returning object(SimpleXMLElement)#1 (0) { }. I even tried converting the XML data to array.
index.php
<?php
$appId ="MFS149250";
$appPass ="5TEBRPCZ";
$brokeCode ="ARN-149250";
$iin = "5011217983";
$xml_data = '<?xml version="1.0" encoding="UTF-8"?>
<NMFIIService>
<service_request>
<appln_id>'.$appId.'</appln_id>
<password>'.$appPass.'</password>
<broker_code>'.$brokeCode.'</broker_code>
<iin>'.$iin.'</iin>
</service_request>
</NMFIIService>';
$URL = "https://uat.nsenmf.com/NMFIITrxnService/NMFTrxnService/IINDETAILS";
$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_MUTE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
//echo "<textarea>".$output."</textarea>";
echo $output;
var_dump(simplexml_load_string($output));
curl_close($ch);
?>
I was trying several examples from here, but nothing seems to work for me.
I need to send this envelope for the request:
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:v2="http://xmlns.oracle.com/oxp/service/v2">
<soapenv:Header />
<soapenv:Body>
<v2:runReport>
<v2:reportRequest>
<v2:attributeLocale>en-US</v2:attributeLocale>
<v2:attributeTemplate>Default</v2:attributeTemplate>
<v2:reportAbsolutePath>/Custom/Financials/Fac/XXIASA_FAC.xdo</v2:reportAbsolutePath>
<v2:dynamicDataSource xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
<v2:parameterNameValues xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
<v2:XDOPropertyList xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</v2:reportRequest>
<v2:userID>user</v2:userID>
<v2:password>password</v2:password>
</v2:runReport>
</soapenv:Body>
</soapenv:Envelope>
This is my code:
$url = 'https://soapurl/v2/ReportService?WSDL';
$headers = array("Content-type: application/soap+xml; charset=\"utf-8\"", "Content-length: " . strlen($xml));
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
print_r($response);
And this is the weird result I am getting back:
��R;o�0��+\ﱁTj�QZ�S_R���m�%sF�#��k�Q�l�����lwjT紅�$�H��Rñ���6OxW2gy�`�_aPƶ �|�\{��:Q��;�S���H���EG�<9���q$�v&gI�ҟ���l��6y��yB���?[��x���X5�a��6��5& ��<8�Q���e`�/F+������{���]������K�(2Q��T���X(�F*ϵ�k��eym����Ӊ��]�M�!y ��"m.�����0z�|�1���g�����}� ������C
Why I'm getting this?
If you used a network sniffer (I would recomend Wireshark), you would see that the data is compressed. This is usually employed server-side to reduce the bandwidth needed. Every single modern browser will decompress automatically, but curl on your application is not. If you saved that string on a file (response.bin, for example) and ran file response.bin, you will see the compressing algorithm employed (probably gzip or deflate).
To solve this, ask curl to decompress the response for you:
curl_setopt($ch,CURLOPT_ENCODING, '');
I have the following code
$URL = 'https://hostedconnect.m5net.com/bobl/bobl';
$xml = '<Command xmlns:m5="http://www.m5net.com/org/m5/data/v2/cti" xmlns:csta="http://www.ecma-international.org/standards/ecma-323/csta/ed5">
<ApplicationContext>BoblConsole</ApplicationContext>
<Arguments xsi:type="org.m5.data.v2.cti.HostedConnectObject" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<csta:MonitorStart>
<csta:monitorObject>
<csta:deviceObject>DEVICE</csta:deviceObject>
</csta:monitorObject>
</csta:MonitorStart>
</Arguments>
<FormattedXml>true</FormattedXml>
<Id>9</Id>
<Name>org.m5.apps.v2.cti.HostedConnect.request</Name>
<Password>PASSWORD</Password>
<User>USER</User>
</Command>';
$ch = curl_init($URL);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array (
'Transfer-Encoding: chunked',
'Content-Encoding: chunked',
'Connection: keep-alive',
'Content-Type: text/xml'
));
curl_setopt($ch, CURLOPT_POSTFIELDS, "$xml");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
$test = stream_get_contents($fp_tmp);
The API is supposed to return XML data, but I'm not sure how to access that data while the cURL is running. I've tried using streams, and writing the data to a file, but none of them seem to work. The cURL request is working properly. When just running it returns 550 bytes, when an event happens that is supposed to return data it returns 9100 bytes. This leads me to believe that the correct thing is happening, but I don't know how to access the data from the curl.
I need to the curl to run continuously, this is for monitoring our phone system via the api provided by our hosting provider.
Try a CURLOPT_WRITEFUNCTION as described under http://docs.php.net/manual/en/function.curl-setopt.php
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($ch, $data) {
static $buffer = '';
$buffer .= $data;
// <-- parse xml data here -->
// <-- remove the consumed part from $buffer -->
return strlen($data);
});
//curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
The tricky party will be parsing the xml data since it's not guaranteed that each single chunk (i.e. $data) is one xml packet - probably not even that each chunk belongs to exactly one xml element/document.
Try to find an xml sax/pull parser that takes chunks of data and parses them as far as possible (...and tells you how much data it did consume, so you can store the remaining data between calls and/or start over with the next element/document).
In this particular case maybe ...just maybe, I would revert to a regular expression to find the start and end tag of the event and then put that (sub-)string into an xml parser.
I am trying to get response form my API via CURL, the method needs to get user data via XML and than returns XML with response data.
I get nothing back. API works well, when I try the same request elsewhere than in PHP, it works. My API requires the data to be sent in application/xml Content-Type.
Any ideas what I am doing wrong?
<?php
$request="https://api.mydomain.com/operation/v1/rest/xml/user/authenticate";
$xml_data='<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<userCredentials>
<userName>name</userName>
<password>password</password>
</userCredentials>';
$ch = curl_init();
//curl_setopt($ch, CURLOPT_MUTE, 1);
curl_setopt($ch, CURLOPT_URL, $request);
//curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, "Content-type: application/xml");
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);
echo "<b>Request:</b> $request <br/>";
echo "<b>Response:</b><pre>".$output."</pre>";
?>
As commented, quick guess (lengthy comment):
echo "<b>Response:</b><pre>".$output."</pre>";
This will output the XML unescaped. Your browser will not display anything inside the browser window, but you should be fine to see something when you view the source of the page.
I've been working on this for days and I can't seem to get it to work. Does anyone see a problem with the code below?
The result is nothing. I get no response from the service whatsoever. I've confirmed that the webservice, written in .Net, can accept and xml string, I've matched their schema, etc. But I get no response back.
I should also mention that I'm new to using web services with php but have done this in .Net countless times.
Additionally, is there a way to test the webservice .asmx to view any type of error output in php just to see if it's even working on the server side?
<?php
$url = 'https://someurl/someservice.asmx';
$xml = '<?xml version="1.0" encoding="utf-8" ?>
<query>
<version>1.0</version>
<login>userName</login>
<password>password</password>
<keyword>cancer</keyword>
</query>';
$c = curl_init();
curl_setopt($c, CURLOPT_URL, $url);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_HEADER, true);
curl_setopt($c, CURLOPT_HTTPHEADER, array("application/x-www-form-urlencoded", "Content-length: ".strlen($xml)));
curl_setopt($c, CURLOPT_POST, true);
curl_setopt($c, CURLOPT_POSTFIELDS, 'xmlInput='.urlencode($xml));
curl_setopt($c, CURLOPT_TIMEOUT, (int)30);
$xmlResponse = curl_exec($c);
curl_close ($c);
echo 'Output :: '.$xmlResponse;
?>
Have you tried adding the following to your request?
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, false);
try without
<?xml version="1.0" encoding="utf-8" ?>
or whrite
<?xml version=\"1.0\" encoding=\"utf-8\" ?>