chop Posted June 26, 2012 Share Posted June 26, 2012 I had this thing working okay at some point. Now it doesn't work at all. I have tested the listener script extensively - the script is out of the book except for the query stuff- and have located the point where it seems to be hanging up as noted below. I am testing this from a sandbox account. <?php // This page handles the Instant Payment Notification communications with PayPal. // Most of the code comes from PayPal's documentation. // This script is created in Chapter 6. // Require the configuration before any PHP code as the configuration controls error reporting: require ('includes/commonDefs.inc.php'); require(CONNECTION); $uid = "215"; // HARD WIRED IN FOR TESTING PURPOSES. THIS SAME $UID IS ALSO IN THE PAYPAL BUTTON // The config file also starts the session // Start by creating a request variable: $req = 'cmd=_notify-validate'; // Add each received key=value pair to the request: foreach ($_POST as $key => $value) { // Get all the POST vars from Paypal $value = urlencode(stripslashes($value)); $req .= "&$key=$value"; // the $req will be sent back to PP for confirmation } // Open a socket connection to PayPal: $fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30); // Test //$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30); // Live if (!$fp) { trigger_error('Could not connect for the IPN!'); } else { // Send the request to PayPal: $header = "POST /cgi-bin/webscr HTTP/1.0\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; fputs ($fp, $header . $req); // Paypal must get back exactly what it sent // Read in the response: while (!feof($fp)) { // keep reading until no more to read // ================================= $res = fgets ($fp, 1024); // get the completed response from Paypal if (strcmp ($res, "VERIFIED") == 0) { // a-okay, proceed // ============ THE ABOVE CONDITIONAL HAS TESTED FOR TRUE // ============ THE CONDITIONAL BELOW NEVER SEEMS TO BE TRUE if ($_POST['payment_status'] == 'Completed'){ I PUT IN AN UPDATE QUERY HERE TO TEST TO SEE IF IT WAS GETTING WITHIN THIS CONDITIONAL. IT DOES NOT. ABOVE THIS CONDITIONAL, IT SEEMS TO WORK OKAY. THIS CONDITIONAL IS A DUPLICATE OF THE ONE IN THE SCRIPT RIGHT BELOW HERE } // ====== THE ABOVE CONDITIONAL NEVER SEEMS TO BE TRUE ===== // Check for the right values: if ( isset($_POST['payment_status']) && ($_POST['payment_status'] == 'Completed') && ($_POST['receiver_email'] == 'chopth_1337786135_biz@gmail.com') && ($_POST['mc_gross'] == 25.00) && ($_POST['mc_currency'] == 'USD') && (!empty($_POST['txn_id'])) ) { // Need the database connection now: // Check for this transaction in the database: $txn_id = mysqli_real_escape_string($dbc, $_POST['txn_id']); $q = "SELECT maaMembersID FROM payments WHERE trans_id='$txn_id'"; $r = mysqli_query ($dbc, $q); Link to comment Share on other sites More sharing options...
Larry Posted June 26, 2012 Share Posted June 26, 2012 So what is the value of $_POST['payment_status']? Link to comment Share on other sites More sharing options...
chop Posted June 26, 2012 Author Share Posted June 26, 2012 The value of payment_status is "pending". I check it by inserting the query (below) just after the line "if (strcmp ($res, "VERIFIED") == 0) { // a-okay, proceed" // check the value(s) of payment_status $ps = $_POST['payment_status']; $q = "INSERT INTO test (my_values) VALUES ('$ps')"; $r = mysqli_query ($dbc, $q); I expected to get more than 1 INSERT however because the query is in a WHILE loop. Maybe there would be many INSERTS as it changed from "pending" to "Completed". But there is only 1! How is the IPN script debugged without a browser window. I have sent variable values in emails to myself and by posting them to a database as above. As I mentioned, this script worked a week ago before I make some changes to it. But the changes were only to the query portions of it which come after the status was "complete". I don't know what happened. Later on... I found this to be a helpful way of detecting errors that might be in the ipn.php (I found no errors in the script above) // tell PHP to log errors to ipn_errors.log in this directory ini_set('log_errors', true); ini_set('error_log', dirname(__FILE__).'/ipn_errors.log'); Link to comment Share on other sites More sharing options...
chop Posted June 27, 2012 Author Share Posted June 27, 2012 Okay, problem solved and a suggestion to all IPN users: I overlooked a feature that the PP sandbox offers which helped me discover the problem in the script. I wish I had seen this earlier as it would have save me hours of debugging. Here is the feature: 1. Go to the sandbox Home page you will see "Test Tools" located in the left column 2. Go here and click on "Instant Payment Notification Simulator" 3. Fill in the necessary information particular to your own site. (note: each time you test with this, make sure you change the "txn_id" to indicate a different transaction than the last one you tried. The simulator eliminates the need to find bugs by testing through your own sandbox pseudo-buyer that you create. It is much much faster! My originally stated problem was that I couldn't get the value of $_POST['payment_status'] to be anything but "pending". But when I tried it in the simulator, I found that it did "Complete" the operation with my ipn.php script - hmmm. I believe that the reason for this is that the "pending" I got was only form the first loop the "while" statement that it was in and that, after a few loops, it probably changes to "Complete" ( I used an UPDATE sql to write the status to a 'test' table to find out what was happening. I don't know why that table wasn't written to multiple time as it looped through the "while" which would have finally yielded a "Complete") I also discovered a great way to help debug this "browserless" covert operation between PP and the listener IPN on my own server: put these lines at the beginning of your ipn.php code ini_set('log_errors', true); ini_set('error_log', dirname(__FILE__).'/ipn_errors.log'); This code will put any generated errors in an "ipn_errors.log" on the same level as your ipn.php script. Choose a point in the code ( such as inside a conditional) where you want to see if the condition is true or false. Then put something that will produce an error like xxx() yielding: [26-Jun-2012 12:37:46] PHP Fatal error: Call to undefined function xxx() in /home/portfoli/public_html/maaa/myIPN.php on line 9 You can do multiple tests like this in only a minute with the simulator. THE ACTUAL PROBLEM WITH MY SCRIPT: I wanted to shoot myself, but the reason it was not updating my database is: $q = "UPDATE".DBTABLE." SET paid_thru = '$newdate' WHERE maaMembersID = $uid LIMIT 1"; Can you see it? It took me 2 days because I was sidetracked by the "pending" problem. No space after the UPDATE within the quotes $q = "UPDATE".DBTABLE I hope this helps anyone having trouble using IPN ...Now I can mow my lawn. Link to comment Share on other sites More sharing options...
Larry Posted July 1, 2012 Share Posted July 1, 2012 Kudos for figuring it out and thanks for sharing. Once again, the classic debugging methods would have caught this: print out the queries being run. Link to comment Share on other sites More sharing options...
chop Posted July 5, 2012 Author Share Posted July 5, 2012 Epilogue to the IPN debacle and caveat to sandbox users: My high from solving this listener script problem was, however, short lived when I tried it (in the sandbox) using a "pay now" button after it had provd successful in the IPN simulator. The button would not work, the $_POST['payment_status'] would get to 'pending' but never 'Completed'. Therefore the script could not be completed. I spent many hours going over the ipn listener code but couldn't figure it out. I tossed in that towel and called tech. support at PayPal. I had to go 3 support levels down before I found someone who figured it out right away. Here it is: The SELLER account CANNOT BE SET TO 'payment review enabled'. You MUST disable this feature or nothing you do with this account will ever get past the 'pending' stage. Even though it will work in the test tools / IPN simulator. I'm not sure if it is enabled by default but you should make sure that it is not. Who'd a thunk it! 1 Link to comment Share on other sites More sharing options...
Larry Posted July 7, 2012 Share Posted July 7, 2012 Ah, that makes sense. Kudos for figuring that out and thanks for sharing. Link to comment Share on other sites More sharing options...
Marie Posted August 28, 2012 Share Posted August 28, 2012 At the present time I am having similar problems with ipn and paypal. I am working with the first model in the book but changing things to suit my situation such as changing the table name "orders" to "pending_users". My ipn doesnt' seemt to be connecting to the database but I am not getting any error messages either. So I am thinking that I may be having this "pending" problem as well. I have mostly been testing my site as a "live" site using my own credit information. However, I do not see exactly where to disable the "payment review enabled". I am looking under my Profile under the Selling section. Any help would be appreciated. Marie Link to comment Share on other sites More sharing options...
chop Posted September 1, 2012 Author Share Posted September 1, 2012 The "payment review enabled" or "disabled" is part of the sandbox testing area. If you are still having problems with IPN or have plans to use paypal on a continuing basis I suggest you set up a PayPal sandbox account. There are several advantages to this besides not having to actually use your credit card to test a site. It is especially important if you use more complicated features like the IPN. In the PP sandbox you get a way to test your IPN script without actually having to create a payment button. Instead, you use The IPN simulator.This is located under the Testing Tools menu. In this environment you can type in the values for all the variables that you would have in the button... buyer info , basic info and even the "custom" variable. When everything is working and your IPN script is updating your database okay. Then you can try making an actual button (still within the sandbox environment) on your server page and click on it . I t should work the same from the button as the simulator. Then, assuming everything is working okay, you're ready to try it on the real payPal site. Note that a PayPal sandbox account is completely separate from any other PP account you might already have. It has nothing to do with your merchant account except that you cannot use the same email address in both accounts. It's a little confusing because when you create a sandbox account, you use a real email and a password so you can log in, like into your merchant account. When you get into the sandbox environment, you create a buyer and a seller account which are "pretend" accounts that have pretend emails and pretend passwords. I kept getting mixed up between the real and not real. That is between my merchant account email/pw , my sandbox email/pw and three different pretend peoples email/pw within the sandbox. But once you have it down, you can use it over again for testing any scenario. Hope that helps. Link to comment Share on other sites More sharing options...
Marie Posted September 6, 2012 Share Posted September 6, 2012 Thank you. It does help. I was using the live PayPal because I had read a few posts where people were having trouble with the PayPal Sandbox. However, I have discovered that it is easier using the LIVE PayPal with a Buy Now button rather than a Subscribe button. Most of it is working but it doesn't seem to be connecting with the database. I have read the code over and over and tested out a few things but my tables never get updated. SO, I may go back to trying it with the Sandbox but I assume the problems will be the same. Marie Link to comment Share on other sites More sharing options...
abigail Posted September 6, 2012 Share Posted September 6, 2012 Just a suggestion, Marie. Try to debug your ipn script by either sending yourself email or writing to a text file. This is to see how far you are getting. Maybe you are not getting to the part that updates the database. 1 Link to comment Share on other sites More sharing options...
chop Posted September 7, 2012 Author Share Posted September 7, 2012 There are indeed some problems with PP sandbox. I don't think they have a budget big enough to keep it running smoothly. I've found links to be broken and page styling to be missing now and then. But they have a pretty good support team and will return an email answer to you in 24 hours. A further note on using sandbox: Use the IPN simulator first to check your IPN script (it's way faster) and make sure you have the following variables plugged into it. Assuming that you're going by the script in the e-commerce book, which has the following lines of code: if ( isset($_POST['payment_status']) && ($_POST['payment_status'] == 'Completed') && ($_POST['receiver_email'] == 'chopth_1337786135_biz@gmail.com') && ($_POST['mc_gross'] == 25.00) && ($_POST['mc_currency'] == 'USD') && (!empty($_POST['txn_id'])) ) { Your variables receiver email, mc gross, mc currency (in your simulator script) must agree with the above or it won't make it past this conditional. Also, if you are updating a database, you should keep changing the txn_id (transaction id) to something different because there aren't supposed to be duplicates. One more thing that I suggest is to change the script that Larry provides in his book in the following way ( if it hasn't been changed already): Instead of: $header .= "POST /cgi-bin/webscr HTTP/1.0\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; you should have: $header .= "POST /cgi-bin/webscr HTTP/1.0\r\n"; $header .= "Host: www.paypal.com\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; with the one additional line. This seems to be a new thing with PP. As Abigail suggests, set up some debugging using something like: $fileName= "checkFile"; file_put_contents ($fileName,$_POST['payment_status']) to write a file that contains variable values to you server OR you stick in the lines: ini_set('log_errors', true); ini_set('error_log', dirname(__FILE__).'/ipn_errors.log'); at the beginning of your script and then put: gotThisFar(); at a strategic point in your script. If the error is listed in your error file "ipn_errors.log" then you know that PayPal the script go at least that far without bombing. I've spent a lot of time recently messing with this so it's fresh in my mind. Let me know if there's anything else I can help with. 1 Link to comment Share on other sites More sharing options...
Marie Posted September 9, 2012 Share Posted September 9, 2012 Thanks for all the help. So I thnk I have put all the debugging code in my ipn.php page. The following is what I got in the errors log: [08-Sep-2012 22:34:03] PHP Fatal error: Call to undefined function gotThisFar() xxxxxxxxxxx/ipn.php on line 98 This is where the gotThisFar line woul be: } elseif (strcmp ($res, "INVALID") == 0) { // log for manual investigation } $fileName= "checkFile"; file_put_contents ($fileName,$_POST['payment_status']); } // End of the WHILE loop. gotThisFar(); // Close the connection: fclose ($fp); } // End of $fp IF-ELSE. ?> SO this is after the point where the data bases should be updated. Also, I discovered that I had "CDN' for the currency rather than 'CAD' which is what PayPal uses - for Canadian currency. I also thought that the ipn notification URL in the PalPal settings was incorrect so I changed that. However, the databases are still not be updated. The expiry date in the database is stil one day earlier and nothing gets entered into the orders table. I am not sure how to change the transaction id. I am still doing it live - and running out of credit cards to use. Apparently, Paypal won't let the same card be used too often which means a user cannot set up any subscriptions for other friends who may not have a credit card. If one person only has ONE credit card but wants to set up more accounts it seems to be a problem. Thanks, Marie Link to comment Share on other sites More sharing options...
Marie Posted September 9, 2012 Share Posted September 9, 2012 Hello, A further note to the above - I am not getting any of the error messages that are near the bottom of the script such as the following - } else { // Problem inserting the order! trigger_error('The transaction could not be stored in the orders table!'); I am assuming that this would show up in the browser. I was wondering about the file: - $uid = (isset($_POST['custom'])) ? (int) $_POST['custom'] : 0; I know it is explained in the book but personally I don't understand what isset is all about. Marie Link to comment Share on other sites More sharing options...
rob Posted September 9, 2012 Share Posted September 9, 2012 I know it is explained in the book but personally I don't understand what isset is all about. http://php.net/manual/en/function.isset.php Marie, you should really learn the basics of PHP before tackling this book. I am assuming that this would show up in the browser. No. The IPN is a listener script, it interacts with paypal directly, there is no interaction between a user (browser) and the script. You should read the tip on page 154 in the book for debugging. If the script is getting to the conditional in your script where the database query is being executed, you should construct the query and dump it to a log file so you can check it is what you're expecting. Link to comment Share on other sites More sharing options...
Marie Posted September 9, 2012 Share Posted September 9, 2012 Sorry meant LINE not file: - $uid = (isset($_POST['custom'})) $ (int) $_POST['custom'] : 0; Marie Link to comment Share on other sites More sharing options...
chop Posted September 9, 2012 Author Share Posted September 9, 2012 "I was wondering about the file: - $uid = (isset($_POST['custom'])) ? (int) $_POST['custom'] : 0;" $uid is "custom" variable that you send to PayPal which stands for the user id (that is, the id that YOU have assigned to the person that is ... buying something from you, whatever). Ultimately, you will send the value of $uid to PayPal from within a PayPal button (as shown on page 152). PayPal will send it back to you in its IPN information so you can then use it to update your database. BUT, before using a button, you can stick the value of $uid in the slot that says "custom" in the IPN simulator. Link to comment Share on other sites More sharing options...
Marie Posted September 9, 2012 Share Posted September 9, 2012 Okay, Thank you rob and chop for your replies. Yes, I probably should have learned a bit more PHP before tackling the book, although for the most part I have been learning as I go along. So I will go "back to the drawing board" for a bit. Marie Link to comment Share on other sites More sharing options...
Marie Posted September 16, 2012 Share Posted September 16, 2012 Hello, I contacted PayPal who sent me a link to a list of PayPal Troubleshooting Tips. https://www.x.com/content/ipn-troubleshooting-steps From this list I saw some potential problems and contacted my web host to see if a Firewall might be blocking any scripts. They said no and I asked if they support Curl or fsockopen and they said that they support both. I looked at the access logs on my server and saw no indication that PayPal had attempted to make a connection. PayPal sandbox is giving me a lot of problems. When I click on various links within the sandbox, I frequently get a Bad Error Request error message on my browser. So I went back to testing it live. I am considering using the "thanks" page to enter information in the orders table and update the users table. Obviously there could be problems there. Anyway, right now I am stumped as I too have looked over the code and re-read the pages and tried some debugging techniques. Marie Link to comment Share on other sites More sharing options...
Marie Posted September 17, 2012 Share Posted September 17, 2012 Okay, Just thought of something. It seems that PayPal is not hitting the ipn script. The ipn script calls for the configuration file and I have put a script in there that redirects the user if their session has expired. So in other words if I try to bring up the ipn script along in the browser, the index page of my website comes up. Could this be as far a Paypal gets? Or should I give the URI to Paypal instead of the URL? Thanks, Marie Link to comment Share on other sites More sharing options...
Larry Posted September 17, 2012 Share Posted September 17, 2012 PayPal won't have a session associated with its communication with the IPN script. Link to comment Share on other sites More sharing options...
Recommended Posts