IPN Listener

<?php
require_once('../includes/init_page_public.php');

//Error log
error_reporting(E_ALL);
set_error_handler('error_handler');
 
function error_handler($no, $msg, $filename, $line){
	$p = 'werror_log.txt';
	$handle = fopen($p, 'w+');

   	$err = "File name: " . $filename . "<br/>" . 
		"Line: " . $line . "<br/>" . 
		"Message: " . $msg . "<br/>";
	//echo $err;
	fwrite($handle, $err . PHP_EOL);
    exit();
}

//Process log
$p = 'ipn_log.txt';
$handle = fopen($p, 'w+');
wlog('Log file created');

function wlog($msg){
	global $handle;
	fwrite($handle, $msg . PHP_EOL);
}


// Read the post from PayPal and add 'cmd' 
$req = 'cmd=_notify-validate'; 
$header = '';

if(function_exists('get_magic_quotes_gpc')) 
{  
	$get_magic_quotes_exists = true; 
} 

$params = $_POST;
foreach ($params as $key => $value) 
// Handle escape characters, which depends on setting of magic quotes 
{  
	if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1){  
		$value = urlencode(stripslashes($value)); 
	} else { 
		$value = urlencode($value); 
	} 
	$req .= "&$key=$value";
} 
wlog($req); 

// Post back to PayPal to validate 
//$paypal = 'www.paypal.com';
$paypal = 'www.sandbox.paypal.com';

$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n"; 
$header .= "Host: " . $paypal . "\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n"; 
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; 
$fp = fsockopen ('ssl://' . $paypal, 443, $errno, $errstr, 30);
wlog($errstr);
 
// Process validation from PayPal 
// TODO: This sample does not test the HTTP response code. All 
// HTTP response codes must be handles or you should use an HTTP 
// library, such as cUrl 
 
if (!$fp) { // HTTP ERROR 
	wlog('Paypal IPN Listener - HTTP Error');
} else { 
	// NO HTTP ERROR 
	fputs ($fp, $header . $req); 
	wlog($errstr);

	while (!feof($fp)) { 
		$res = fgets ($fp, 1024); 
		wlog($res);

		if (strcmp ($res, "VERIFIED") == 0 && strcmp ($params["payment_status"], "Completed") == 0) { 
			wlog("response verified");
			// TODO: 
			// Check the payment_status is Completed 
			// Check that txn_id has not been previously processed 
			// Check that receiver_email is your Primary PayPal email 
			// Check that payment_amount/payment_currency are correct 
			// Process payment 

			/* If 'VERIFIED', send an email of IPN variables and values to the 
			specified email address 
			foreach ($_POST as $key => $value){ 
				$emailtext .= $key . " = " .$value ."\n\n"; 
			} */


			//Check receiver email
			//if(strcmp ($params["receiver_email"], "[email protected]") <> 0){
			//	wlog("Receiver email is not valid");
			//	break;
			//}

			//Check transaction id
			//if(strlen($err) == 0 && txnExists($params["txn_id"]) == true){
			//	$err = "Transaction ID: " . $params["txn_id"] . " exists already";
			//	break;
			//}

			//Check payment gross according to product ID
			//if($err == "" && checkGross($productID, $_POST["mc_gross"], $_POST["mc_currency"], $_POST["exchange_rate"]) == false){
			//	$err = "Payment gross amount is not equivalent to the setting of this product: " . $_POST["txn_id"];
			//}

			$sql = "INSERT INTO `orders` (`payment_vender`, `account_id`, `product_id`, 
`payment_status`, `product_name`, `receiver_id`, `receiver_email`, `transaction_id`, `transaction_type`, 
`invoice_number`, `item_name`, `item_number`, `quantity`, `charset`, `currency`, `exchange_rate`, `fee`, 
`gross`, `country`, `payer_email`, `payment_date`, `created_time`, `updated_time`) VALUES (" . 
				$db->formatSQLInput(1) . ", " . 
				$db->formatSQLInput(0) . ", " . 
				$db->formatSQLInput(0) . ", " . 
				$db->formatSQLInput($params['payment_status']) . ", " . 
				$db->formatSQLInput('Test') . ", " . 
				$db->formatSQLInput($params['receiver_id']) . ", " . 
				$db->formatSQLInput($params['receiver_email']) . ", " . 
				$db->formatSQLInput($params['txn_id']) . ", " . 
				$db->formatSQLInput($params['txn_type']) . ", " . 
				$db->formatSQLInput($params['invoice']) . ", " . 
				$db->formatSQLInput($params['item_name']) . ", " . 
				$db->formatSQLInput($params['item_number']) . ", " . 
				$db->formatSQLInput($params['quantity']) . ", " . 
				$db->formatSQLInput($util->out($params, 'charset', 'UTF-8')) . ", " . 
				$db->formatSQLInput($util->out($params, 'mc_currency', 'USD')) . ", " . 
				$db->formatSQLInput($util->out($params, 'exchange_rate', '')) . ", " . 
				$db->formatSQLInput($params['mc_fee']) . ", " . 
				$db->formatSQLInput($params['mc_gross']) . ", " . 
				$db->formatSQLInput($params['residence_country']) . ", " . 
				$db->formatSQLInput($params['payer_email']) . ", " . 
				$db->format_sql_date($params['payment_date']) . ", " . 
				$db->format_sql_date(NULL, true) . ", " . 
				$db->format_sql_date(NULL, true) . " " . 
				")";
			wlog($sql);

			$rs = $db->query($sql);
		} else if (strcmp ($res, "INVALID") == 0) { 
			//If 'INVALID', send an email. TODO: Log for manual investigation. 
			$values = 'response: INVALID';
			wlog($values);
		}
	} 
}

fclose($fp);


if($err == ""){
	wlog("Store Listener - Completed", "Transaction");
}else{
	wlog("Store Listener - Error");
}
?>

 

Reference:

  1. http://stackoverflow.com/questions/11810344/paypal-ipn-bad-request-400-error
  2. https://developer.paypal.com/webapps/developer/applications/ipn_simulator
  3. https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNIntro/#protocol_and_arch
  4.