On page 172, number 9, I had to change 'payment_status', 'receiver_email' and 'mc_gross' from === to == because the IPN would not work.
// Check for the right values: if ( isset($_POST['payment_status']) && ($_POST['payment_status'] == 'Completed') && ($_POST['receiver_email'] == 'treasurer@nmsc.org') && ($_POST['mc_gross'] == 40.00) && ($_POST['mc_currency'] === 'USD') && (!empty($_POST['txn_id']))
Because ipn.php is not a page you can test normally (like, with echo statements), how I troubleshooted this, was I created a text file on the server called 'ipn_troubleshooter.txt" and where I would normally put echo statements to find out where the code is broken, I instead made fwrite calls to the text file. If the file didn;t get updated, I knew the code was broken at the point I called the fwrite. In this case it was "&& ($_POST['payment_status'] === 'Completed')" that was broken, so I changed it to == and it worked, then I made may way through the others, fixing only the ones that were broken.