I have a Magento store that has been converted to a "one deal at a time" type store, and the checkout process is broken. I've been trying to debug this, but have hit a wall, primarily due to my limited understanding of Magento.
On the saveOrder step, when clicking "Place Order", the page shows "submitting order information, then the message clears and the shopper is still on the Order Review page.
I've analyzed with Firebug and HttpFox, and I can see the order information is being sent
(Request-Line) POST /checkout/onepage/saveOrder/ HTTP/1.1
Host www.domainname.com
User-Agent Mozilla/5.0 (Windows NT 6.0; rv:2.0) Gecko/20100101 Firefox/4.0
Accept text/javascript, text/html, application/xml, text/xml, */*
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip, deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 115
Connection keep-alive
X-Requested-With XMLHttpRequest
X-Prototype-Version 1.6.0.3
Content-Type application/x-www-form-urlencoded; charset=UTF-8
Referer https://www.domainname.com/checkout/onepage/
Content-Length 178
Cookie frontend=cd60252d28cd115d4096cb2bb5b6a043
Pragma no-cache
Cache-Control no-cache
Post Data shows all of the required information:
payment[method] authorizenet
payment[cc_type] VI
payment[cc_number] 4111111111111111
payment[cc_exp_month] 5
payment[cc_exp_year] 2012
payment[cc_cid] 987
My problem seemed similar to this post:
http://fishpig.co.uk/magento-tutorials/magento-checkout-error-undefined-javascript-alert
but I'm not getting an "Undefined" alert, so I added the "else" statement below:
nextStep: function(transport){
if (transport && transport.responseText) {
alert(transport.responseText);
try{
response = eval('(' + transport.responseText + ')');
}
catch (e) {
response = {};
}
if (response.redirect) {
location.href = response.redirect;
return;
}
if (response.success) {
this.isSuccess = true;
window.location=this.successUrl;
}
else{
var msg = response.error_messages;
if (typeof(msg)=='object') {
msg = msg.join("\n");
}
alert(msg);
}
if (response.update_section) {
$('checkout-'+response.update_section.name+'-load').update(response.update_section.html);
response.update_section.html.evalScripts();
}
if (response.goto_section) {
checkout.gotoSection(response.goto_section);
checkout.reloadProgressBlock();
}
} else {
alert('transport.responseText');
}
},
I am getting the JS alert with no text, so it looks like transport.reponseText is empty. The main references to empty response text I've found appear to be related to same-origin policy, which I don't think applies, because my AJAX post is to and from www.domainname.com.
When I call the saveOrder function directly in the browser, I'm receiving a valid response:
https://www.domainname.com/checkout/onepage/saveOrder
{"success":false,"error":true,"error_messages":"Credit card number mismatch with credit card type"}
and HTTPFox shows I'm getting a 200 response from the Ajax call, but the responsetext is simply empty. I find no PHP errors or errors in Magento's exceptions log. The only thing I'm finding that might be related is "Headers already sent' in Magento's system log:
</pre>
2011-09-03T12:14:21+00:00 DEBUG (7): HEADERS ALREADY SENT: <pre>[0] wwwroot/app/code/core/Mage/Core/Controller/Response/Http.php:50
[1] wwwroot/lib/Zend/Controller/Response/Abstract.php:726
[2] wwwroot/app/code/core/Mage/Core/Controller/Response/Http.php:82
[3] wwwroot/app/code/core/Mage/Core/Controller/Varien/Front.php:169
[4] wwwroot/app/Mage.php:459
[5] wwwroot/index.php:67
</pre>
Does anyone have any suggestions why else the responseText is coming back empty?
Custom modules were at fault. Disabling all of the custom modules in the Magento admin does not actually disable them, it only "disables their output".
Setting False in the module configuration resolved the invalid headers error, at which point I was able to debug the custom module issue that was causing the AJAX checkout errors.
Related
I googled this question and tried all suggestions but nothing works.
I tried this code: https://developer.paypal.com/docs/classic/ipn/ht_ipn/ but it don't work. Just copy-pasted it and deleted old magick_quotes routunes.
I tried this code: http://samples.geekality.net/view-source.php?file=ipn/ipn_handler.class.php and it also do not work.
In all cases I tried to do following:
$req = 'cmd=_notify-validate&' . file_get_contents('php://input');
To ensure I sent to IPN exactly what it sent to me. In addition I used the debug proxy (Fiddler) and saved what IPN sent to me and what I sent to IPN. The requests bodies are byte-to-byte identical except my request is prefixed by the cmd=_notify-validate& string.
Yes, I checked I use proper sandbox URL. Here are entire requests bodies:
What IPN sent to me: (I just replaced personal data to XXX)
POST http://localhost.loc/en/payment/success/1 HTTP/1.1
Host: localhost.loc
Connection: keep-alive
Content-Length: 921
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: null
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.81 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
mc_gross=1.00&protection_eligibility=Ineligible&payer_id=5XNKM66NSDKC4&tax=0.00&payment_date=05%3A34%3A11+Jun+01%2C+2015+PDT&payment_status=Completed&charset=utf-8&first_name=XXX&mc_fee=0.33¬ify_version=3.8&custom=topup%3A262262%3A1%3A1433162020&payer_status=verified&business=XXX&quantity=1&payer_email=XXX&verify_sign=AG58dBsn5g2z8O8NEjotbuJGP14PAIpZ4k26VL8IyhaDPkcDRj002Keq&memo=hmgvjgjhgfjhfggjhfjtfgjh&txn_id=4CN141026K278934Y&payment_type=instant&last_name=XXX&receiver_email=XXX&payment_fee=0.33&receiver_id=DCMXPXGX4QX6J&txn_type=web_accept&item_name=Account+top+up&mc_currency=USD&item_number=Account+262262+top+up&residence_country=US&test_ipn=1&handling_amount=0.00&transaction_subject=topup%3A262262%3A1%3A1433162020&payment_gross=1.00&shipping=0.00&auth=ANSTBwT3znll-gJQZO2cLoV5QJFW9v8W.FqyWxffdtI0L-9mfsoe2xRL44M86Sn2XtYGtcqG4Fjjel1kdYZyxpQ
What I sent to IPN:
POST https://www.sandbox.paypal.com/cgi-bin/webscr HTTP/1.1
Host: www.sandbox.paypal.com
Accept: */*
Content-Length: 942
Content-Type: application/x-www-form-urlencoded
cmd=_notify-validate&mc_gross=1.00&protection_eligibility=Ineligible&payer_id=5XNKM66NSDKC4&tax=0.00&payment_date=05%3A34%3A11+Jun+01%2C+2015+PDT&payment_status=Completed&charset=utf-8&first_name=XXX&mc_fee=0.33¬ify_version=3.8&custom=topup%3A262262%3A1%3A1433162020&payer_status=verified&business=XXX&quantity=1&payer_email=XXX&verify_sign=AG58dBsn5g2z8O8NEjotbuJGP14PAIpZ4k26VL8IyhaDPkcDRj002Keq&memo=hmgvjgjhgfjhfggjhfjtfgjh&txn_id=4CN141026K278934Y&payment_type=instant&last_name=XXX&receiver_email=XXX&payment_fee=0.33&receiver_id=DCMXPXGX4QX6J&txn_type=web_accept&item_name=Account+top+up&mc_currency=USD&item_number=Account+262262+top+up&residence_country=US&test_ipn=1&handling_amount=0.00&transaction_subject=topup%3A262262%3A1%3A1433162020&payment_gross=1.00&shipping=0.00&auth=ANSTBwT3znll-gJQZO2cLoV5QJFW9v8W.FqyWxffdtI0L-9mfsoe2xRL44M86Sn2XtYGtcqG4Fjjel1kdYZyxpQ
Can anyone help me what I do wrong?
Thanks.
AARRRRGH!!!!!!!! I have only dirty words to PayPal!!!!!!! The problem was in... (drumroll... tadam!) in the charset field! No, its value must be the same as IPN sent it to you, but... in UPPERCASE! IPN sends it in lowercase! So you MUST modify IPN data to verify it successfully regardless manual tells us to return data back "as-is". PayPal bug?
So my final working code is: (using HTTP_Request2)
protected function verifyPostData() {
$this->request->setBody('cmd=_notify-validate&' . str_replace('=utf-8', '=UTF-8', file_get_contents('php://input')));
$response = $this->request->send();
if ($response->getStatus() != 200) {
throw new \RuntimeException("Transaction data verification request failed with code {$response->getStatus()}");
}
$content = trim($response->getBody());
return ($content == 'VERIFIED');
}
How I did it: I sent the PDT request for this transaction and obtained transaction data. Then I made field to field comparison of PDT and IPN data. PDT have no some IPN fields such as auth, verify_sign and test_ipn. But all other fields seems must be the same. And the only difference was in the characters case of the charset field. Then I tried to verify modified data and unexpectedly it become successful!
This is a recent PayPal bug, when the customer completes a payment and clicks on "Click here to return.." instead of waiting a few seconds, the parameters passed to the PDT script on your site are sent in lowercase.
This also messes up things like a case-sensitive or encoded cm/custom parameter.
Apparently PayPal are aware of it.
MORE EDITS
After testing the code on several browsers, it appears that I am only able to get the XMLHttpRequest.lengthComputable to be true on FireFox, thus giving me a download percentage. It returns false for both Chrome and Safari... any ideas to solve this? I have included the header("Access-Control-Allow-Origin: *"); tag at the top of my PHP script.
EDIT
Alright, with the help from the comments, I have my PHP sending a Content-Length however, the evt.total is still returning a 0. Any idea?
After further testing, it appears that evt.lengthComputable is set to false - therefore it is ignoring evt.total... now I need to find out why that is.
Here is the data in the Headers
Request Method:GET
Status Code:200 OK
Request Headers
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Host:(deleted data here for confidential reasons)
Origin:(deleted data here for confidential reasons)
Referer:(deleted data here for confidential reasons)
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36
Response Headers
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Encoding:gzip
Content-Length:1914150
Content-Type:application/json
Date:Wed, 25 Feb 2015 22:38:22 GMT
Server:Apache
Vary:Accept-Encoding
ORIGINAL POST
Maybe this is a dumb question, but here it is...
I'm working on a private PhoneGap app which is essentially a company directory. When the app first starts, it detects that the stored JSON is empty has not yet been downloaded and prompts the user to start the download.
I obtain the JSON data using an AJAX call. The JSON is generated by PHP on our server that queries the database, builds the array, then json_encode and echos the output.
The data transfers to our app and everything is working nicely, however, I'd like to build a "Progress Meter" for the download which requires me to know exactly how large the data being sent over is. I know PHP has some ways to get file size of certain files such as filesize($somefile), but how would I be able to measure the byte size of the JSON data? Can this even be done? Here is some of the code I am using...
PHP Building The JSON Data
while(...fetch the data) {
$output[] =
array (
"id" => $row['id'],
"firstname" => $row['firstname'],
"lastname" => $row['lastname'],
"jobtitle" => $row['jobtitle'],
"phone" => $row['phone'],
"cell" => $row['cell'],
"email" => $row['email'],
"department" => $row['department'],
"sub" => $row['sub'],
"image" => $row['image']
);
}
echo json_encode($output);
Here I am getting the JSON with AJAX: (I am using Framework7 - hence the $$)
$$.ajax({
url: "my-site-here.php",
dataType: "json",
beforeSend: function(XMLHttpRequest) {
//Download Progress Attempt (Found By Googling)
XMLHttpRequest.addEventListener("progress", function(evt){
//console.log("Downloaded: " + evt.loaded) <-- THIS IS WORKING;
//console.log("Total: " + evt.total) <-- THIS RETURNS 0;
var percentComplete = evt.loaded / evt.total;
console.log(percentComplete);
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
console.log(percentComplete);
} else {
// console.log("Cannot Compute File Size"); <-- THIS IS WHAT OUTPUTS
}
}, false);
},
success: function(json) {
// GETS DATA, RENDERS IT
}
});
Thanks in advance for some insight!
I found this solution here: https://stackoverflow.com/a/24073356/2163226.
All I had to do was edit my .htaccess file to expose the Content-Length header.
Now everything is working as intended!
Thank you all for the help and suggestions!
EDIT - Misunderstood the request process.
I am running Apache2 and PHP 5 on Linux, and I'm getting some strange behavior with the php://input stream.
For some GET requests the stream is not empty like it should be. Instead, the php://input stream contains the entire GET request. I have worked around the issue but I would like to know if I should file a bug about this, or if it is "desired but undocumented" behavior.
Details
Early in the request processing, I call:
$in = file_get_contents('php://input');
if ( !empty($in) )
$post_data = json_decode($in);
if ( !empty($in) && is_null($post_data) ) {
// output some error info and exit
}
Usually when a request does not have a body then $in is empty and all is right with the world. But sometimes a GET request will have a body, and that body will be the entire request. Of course you can't json-decode that data, and the error condition gets hit.
This only happens with some requests. For example, this request does not exhibit the error:
GET /os/invitations/kkkkkk HTTP/1.1
Host: our.machine.com
Content-Type: application/json
Authorization: Basic aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa==
But this request, which is routed through some proxies and VPNs, does trigger the error.
GET http://some.proxy.at.some.big.company.com:7080/cvp-out/cmmproxy/os/invitations/d66065566dba541c8ba6a70329684645 HTTP/1.1
Content-Type: application/json
Authorization: Basic aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa==
Clientid: abc
User-Agent: Java/1.6.0
Host: some.proxy.at.some.big.company.com:7080
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
X-Remote-Addr: 53.231.244.171
X-Remote-Host: 53.231.244.171
X-Server-Name: some.proxy.at.some.big.company.com
X-Server-Port: 7080
X-Scheme: http
I spent hours treating this like a routing/dispatch problem, but it turned out to be our code. The fix was, of course, to only read from the input stream when you are expecting data:
if ( in_array( $_SERVER['REQUEST_METHOD'], array('PUT', 'POST') )) {
$in = file_get_contents('php://input');
if ( !empty($in) )
$post_data = json_decode($in);
}
Is this a known issue? Does it happen unpredictably? Should I file a bug?
As far as i know, that's not an error. We understand that a GET request shouldnt have a body, but in the docs of php:// they say nothing about wich types of requests will generate an input, so it could be any method. And for sure it is not limited to POST, since the mention at least PUT and PROPFIND.
So at any rate, your solution is a must.
There is a asp.net driven site where I can login and fill a form to place a order after a succesful login. This needs to be done by my server with curl.
Whenever I do this with my browser there is nothing special.
I go to example.com/login.aspx. Fill in fields and post it back. I get a index page back for logged in users. After this i need to click on a link to the form for order placement. Doing this gives me the form, which I fill and send back.This yields the wanted result of an placed order. Analysing the source revealed the page gets submitted through javascript,but the server cannot know how the request is sent if the request is identical. During this process i kept track of all the post requests send from my browser.
Having all the post requests, i wrote some code to do the same with curl.
The algorithm is:
Send a get request to obtain the example.com/login.aspx page
Parse the responds for any hidden fields(as they are used to mimic a statefull connection)
Post the state and the logindata to example.com/login.aspx
Parse the state send back and update it
Get form for order placement
Parse & update the state again
Post the state and the same post data that my browser sent
Print info to file instead of STDERR
During the process cookies are used with curl.
Everything goes smooth until the last POST. Instead of a "Success" or "Failure" result, I get my original form returned to me, with no validation errors mentioned. If I delibarely fill in gibberish or leave some things empty with my browser I get validation errors shown.
I have no experience with asp.net and am completely stuck here, so forgive me if this question is too specific.
Question:
If the headers and post data are exactly the same as from my browser, how can my curl operation have a different result?
For completeness:
POST from browser:
POST /DataEntry.aspx HTTP/1.1
Host: www.iftin.co
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:16.0) Gecko/20100101 Firefox/16.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: nl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: https://www.iftin.co/DataEntry.aspx
Cookie: ASP.NET_SessionId=SomethingX; .hawAuth=SomethingY
Content-Type: application/x-www-form-urlencoded
Content-Length: 10111
Post send by Curl:
POST /DataEntry.aspx HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:16.0) Gecko/20100101 Firefox/16.0
Host: www.iftin.co
Referer: https://www.iftin.co/DataEntry.aspx
Cookie:.hawAuth=SomethingZ; ASP.NET_SessionId=SomethingW
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: nl,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 25236
Expect: 100-continue
Content-Type: application/x-www-form-urlencoded;boundary=----------------------------5bb8ec4e5ecc
If people want to see some code, let me know. Thanks for reading and spending time on this.
Ater writing this, I noticed that the Content-Length for my curl request is substantially bigger than for my browsers request. I copied all parameters in the body of the Post of the browser to my code and passed it to curl in a array.
So curl has to add some data to the request by default. Is this the case?
The CURLOPT_SSL_VERIFYPEER is set to false, while the page uses SSL. Could this be it? Why?
I'm been stuck on this problem for a while and I'm pretty sure it must be something quite simple that hopefully someone out there can shed some light on.
So, I'm currently using jQuery UI's Autocomplete plugin to reference and external PHP which gets information from a database (in an array) and sends it to a JSON output.
From my PHP file (search.php) when I do this:
echo json_encode($items);
My output (when looking at the search.php file) is this:
["Example 1","Example 2","Example 3","Example 4","Example 5"]
Which is valid JSON according to jsonlint.com
The problem is that when I use jQuery UI's Autocomplete script to reference the external search.php file, Chrome just gives me the following error:
GET http://www.example.com/search.php?term=my+search+term 404 (Not Found)
I have tried inputting the JSON code straight into the 'Source:' declaration in my jQuery, and this works fine, but it will not read the JSON from the external PHP file.
Please can someone help?
Here's my code:
HMTL
<p class="my-input">
<label for="input">Enter your input</label>
<textarea id="input" name="input"
class="validate[required]"
placeholder="Enter your input here.">
</textarea>
</p>
jQuery
$(function() {
$( "#input" ).autocomplete({
source: "http://www.example.com/search.php",
minLength: 2
});
});
PHP
header("Content-type: application/json");
// no term passed - just exit early with no response
if (empty($_GET['term'])) exit ;
$q = strtolower($_GET["term"]);
// remove slashes if they were magically added
if (get_magic_quotes_gpc()) $q = stripslashes($q);
include '../../../my-include.php';
global $globalvariable;
$items = array();
// Get info from WordPress Database and put into array
$items = $wpdb->get_col("SELECT column FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY column ASC");
// echo out the items array in JSON format to be read by my jQuery Autocomplete plugin
echo json_encode($items);
Result
In browser, when information is typed into #input
GET http://www.example.com/search.php?term=Example+1 404 (Not Found)
Update: the real PHP url is here: http://www.qwota.co.uk/wp/wp-content/themes/qwota/list-comments.php?term=Your
Please help!
UPDATE: ANSWER
The answer to my problem has been pointed out by Majid Fouladpour
The problem wasn't with my code but rather with trying to use WordPress' $wpdb global variable as (as far as I understand) it includes it's own headers, and anything outside of it's usual layout will result in a 404 error, even if the file is actually there.
I'm currently trying to get around the problem by creating my own MySQL requests and not using WordPress's global variables / headers.
PS. Majid, I'll come back and give you a 'helpful tick' once StackOverflow lets me! (I'm still a n00b.)
Are you sure the path source: "http://www.example.com/search.php" is correct?
You have to make sure that the target URL exists. If you are really using http://www.example.com/search.php then, wk, it simply does not exist, so this is why it does not work.
Update
Since you have a real URL that's working (I tested it!), here are a few steps you can take:
Make sure there's no typo. If there's one, fix it.
Make sure you can open that URL from your browser. If you cannot, then you might be having network access problems (firewall, proxy, server permission issues, etc.)
Try redirecting to another know URL, just to make sure. The 404 error is really a "not found" error. It cannot be anything else.
I think the include is the issue. As Majid pointed out... use the below include instead.
include("../../../wp-load.php");
Good luck!
Your apache server is sending wrong headers. Here is a pair of request and response:
Request
GET /wp/wp-content/themes/qwota/list-comments.php?term=this HTTP/1.1
Host: www.qwota.co.uk
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Cookie: __utma=142729525.1341149814.1305551961.1305551961.1305551961.1; __utmb=142729525.3.10.1305551961; __utmc=142729525; __utmz=142729525.1305551961.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Response headers
HTTP/1.1 404 Not Found
Date: Mon, 16 May 2011 13:28:31 GMT
Server: Apache
X-Powered-By: PHP/5.2.14
X-Pingback: http://www.qwota.co.uk/wp/xmlrpc.php
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Pragma: no-cache
Last-Modified: Mon, 16 May 2011 13:28:31 GMT
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
Response body
["Bake 'em away... toys.","Content precedes design. Design in the absence of content is not design, it\u2019s decoration.","Hanging on in quiet desperation is the English way.","I'm a reasonable man, get off my case.","Look at me, Damien! It's all for you!","Never get out of the boat... absolutely god damn right.","That gum you like is going to come back in style.","The secret to creativity is knowing how to hide your sources.","Things could be different... but they're not.","Your eyes... they turn me."]
So, even though you receive back response from the server, it has HTTP/1.1 404 Not Found in the headers. Someone may be able to investigate this and provide a potential reason and solution.