$var) { $var = urlencode(stripslashes($var)); $resp .= "&$parm=$var"; } // STEP 3 - Extract the data PayPal IPN has sent us, into local variables $item_name = $_POST['item_name']; $item_number = $_POST['item_number']; $payment_status = $_POST['payment_status']; $payment_amount = $_POST['mc_gross']; $payment_currency = $_POST['mc_currency']; $txn_id = $_POST['txn_id']; $receiver_email = $_POST['receiver_email']; $payer_email = $_POST['payer_email']; $record_id = $_POST['custom']; // Right.. we've pre-pended "cmd=_notify-validate" to the same data that PayPal sent us (I've just shown some of the data PayPal gives us. A complete list // is on their developer site. Now we need to send it back to PayPal via HTTP. To do that, we create a file with the right HTTP headers followed by // the data block we just createdand then send the whole bally lot back to PayPal using fsockopen // STEP 4 - Get the HTTP header into a variable and send back the data we received so that PayPal can confirm it's genuine $httphead = "POST /cgi-bin/webscr HTTP/1.0\r\n"; $httphead .= "Content-Type: application/x-www-form-urlencoded\r\n"; $httphead .= "Content-Length: " . strlen($resp) . "\r\n\r\n"; // Now create a ="file handle" for writing to a URL to paypal.com on Port 443 (the IPN port) $errno = ''; $errstr = ''; $fh = fsockopen('ssl://www.paypal.com', 443, $errno, $errstr, 30); // STEP 5 - Nearly done. Now send the data back to PayPal so it can tell us if the IPN notification was genuine if (!$fh) { // Uh oh. This means that we have not been able to get thru to the PayPal server. It's an HTTP failure // // You need to handle this here according to your preferred business logic. An email, a log message, a trip to the pub.. } // Connection opened, so spit back the response and get PayPal's view whether it was an authentic notification else { fputs($fh, $httphead . $resp); while (!feof($fh)) { $readresp = fgets($fh, 1024); if (strcmp($readresp, "VERIFIED") == 0 && $payment_status === "Completed") { // Hurrah. Payment notification was both genuine and verified // // Now this is where we record a record such that when our client gets returned to our success.php page (which might be momentarily // (remember, PayPal tries to stall users for 10 seconds after purchase so the IPN gets through first) or much later, we can see if the // payment completed; and if it did, we can release the download. You can go about this synchronisation between listener.php // and success.php in many different ways. How you do it mostly depends on your need for security; but here is one way I do it: // // When the client initiates the purchase by clicking the "buy" button, I write a new "unconfirmed" payment record in my Payments // table; this includes all the details of what they wish to purchase and their session-ID. I then pass the record "id" of this pending entry in the CUSTOM // parameter to PayPal when it processes my site visitor tranaction. // // After PayPal processes the transation, it doesn't return the client to your site immediately; it conveniently stalls them for around // 10 seconds, during which it quickly calls your listener program (this program) to give it the good news. I then extract the record_id // that was inserted in the Payments table database that was created just before the client was sent to PayPal, but now I know that // the payment is VERIFIED, so I can update the record in the PAYMENTS table from "Pending" to "Completed". // // When (or if) the user returns to my "Auto Return" success.php page, I query the database for all "Completed" transactions with the // same Session_id, read the digital products that they have purchased and then release them as downloadable links in // success.php. // // Yes, session_id is not totally reliable, but you could use cookies, or you could use a comprehensive user // registration, logon & password retrieval system that would give you the degree of "lock down" you require. Your choice. $post = get_post($record_id); update_post_meta($post->ID,'status','Paid'); $postmeta = get_post_meta($post->ID); $clients = json_decode(get_option('superbill_clients'),true); $client = $clients[$postmeta['client']]; list($sender_name, $sender_email) = json_decode(get_option('superbill_email_settings'), true); wp_mail($client['email'],'Invoice paid',file_exists(plugin_dir_path(__FILE__) . '/email/superbill_custom_email_paid.txt') != false ? file_get_contents(plugin_dir_path(__FILE__) . '/email/superbill_custom_email_paid.txt') : file_get_contents(plugin_dir_path(__FILE__) . '/email/superbill_default_email_paid.txt'),'From: '.$sender_name.' <'.$sender_email.'>'); } else if (strcmp($readresp, "INVALID") == 0) { // Man alive! A hacking attempt? } } fclose($fh); } // // // STEP 6 - Pour yourself a cold one. // // skipIPN: FreshLondon: Invoices (DKK) https://invoices-dkk.freshlondon.dev Fri, 01 May 2026 11:08:07 +0000 en-US hourly 1 https://wordpress.org/?v=7.1.4