I dug this up from the dusty box in the garage lol here is a really old code for the IPN file, im sure it has changed alittle by now but i would not be surprised if it has not. This file is not provided by paypal, we have to write our own and this worked way back in the day.
as you can see with this code
$custom = $_POST['option_name1'];
that i had to use a oddball field in order to use my custom field. My custom field on this one was the record number of the pre sale data, that way i could go right to the record and update it. Im sure not all of this code is perfect but at the time it was working and i did not know any better.
You can name the file anything you want but you have to tell paypal what the file location is in the form input, i dont remember the var name you use for the ipn input url value.
// STEP 1: Read POST data
// reading posted data from directly from $_POST causes serialization
// issues with array data in POST
// reading raw POST data from input stream instead.
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
foreach ($raw_post_array as $keyval)
{
$keyval = explode('=', $keyval);
if (count($keyval) == 2)
{
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
}//close foreach
//read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($myPost as $key => $value)
{
$value = urlencode($value);
$req .= "&$key=$value";
}//close foreach
if(DEBUGTHIS == true || DEBUGTHIS == 1)
{
if(!empty($req))
{
error_log(date('[Y-m-d H:i e] '). "Req is loaded and ready - going to next step: ". PHP_EOL, 3, LOG_FILE);
}else{
error_log(date('[Y-m-d H:i e] '). "Req FAILED and is NOT loaded - something went wrong: ". PHP_EOL, 3, LOG_FILE);
}//close else
}//close if
// STEP 2: Post IPN data back to paypal to validate
//without this step anyone can fake ipn
// change to [...]sandbox.paypal[...] when using sandbox to test
//original is paypay.com
$ch = curl_init('https://www.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
if(DEBUGTHIS == true || DEBUGTHIS == 1)
{
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
error_log(date('[Y-m-d H:i e] '). "Turned on curl headers and output: ". PHP_EOL, 3, LOG_FILE);
}//close if
// Set TCP timeout to 30 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path
// of the certificate as shown below.
// curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
$res = curl_exec($ch);
if(DEBUGTHIS == true || DEBUGTHIS == 1)
{
error_log(date('[Y-m-d H:i e] '). "Here is the output from curl execute from paypal: ". $res . PHP_EOL, 3, LOG_FILE);
}//close if
if (!$res)
{
// error_log("Got " . curl_error($ch) . " when processing IPN data");
if(DEBUGTHIS == true || DEBUGTHIS == 1)
{
error_log(date('[Y-m-d H:i e] '). "Cant connect to PayPal to validate IPN message: ". curl_error($ch) . PHP_EOL, 3, LOG_FILE);
}//close if
curl_close($ch);
exit;
}//close if res
curl_close($ch);
// STEP 3: Inspect IPN validation result and act accordingly
$checkForVerified = strpos($res, "VERIFIED");
if(!$checkForVerified === false )
{
if(DEBUGTHIS == true || DEBUGTHIS == 1 )
{
error_log(date('[Y-m-d H:i e] '). "Verified - found word VERIFIED at pos: ". $checkForVerified . PHP_EOL, 3, LOG_FILE);
}//close if
// SOME ITEMS YOU MIGHT CHECK
// check whether the payment_status is Completed DONE
// check that txn_id has not been previously processed DONE
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process payment DONE
// assign posted variables to local variables
//EVERYTHING IS CLEANED ON THE FUNCTION SIDE AFTER THE HANDOVER
//gross sale
if ($_POST['mc_gross'] != NULL)
{
$sum = $_POST['mc_gross'];
}else{
$sum = $_POST['mc_gross1'];
}//close else
// transaction id
$tid = $_POST['txn_id'];
//tax
$tax = $_POST['tax'];
//fee
$fee = $_POST['mc_fee'];
//shipping
$shipping = $_POST['mc_shipping'];
//payment status
$payment_status = $_POST['payment_status'];
//currency - see note above
$pay_currency = $_POST['mc_currency'];
//custom can be returned in either var name
if($_POST['custom'] != NULL)
{
$custom = $_POST['custom'];
}else{
$custom = $_POST['option_name1'];
}//close else
//country
$scountry = $_POST['address_country'];
//log
$pay_notify_log = var_export($_POST, true);
//time
$time = time();
// Insert actions here
if ($payment_status == "Completed" || $payment_status == "completed")
{
if(DEBUGTHIS == true || DEBUGTHIS == 1)
{
error_log(date('[Y-m-d H:i e] '). "Verified COMPLETED - payment status value is: ". $payment_status . PHP_EOL, 3, LOG_FILE);
}//close if
//ready for db update
$updatepayment = updateThePaymentArchive($tid,$payment_status,$time,$scountry,$sum,$pay_notify_log,$custom);
}else{
if(DEBUGTHIS == true || DEBUGTHIS == 1)
{
error_log(date('[Y-m-d H:i e] '). "NOT Completed - payment status is: ". $payment_status . PHP_EOL, 3, LOG_FILE);
}
// Exit since payment status is not Completed
exit;
}//close if else completed
}elseif(!strpos($res, "INVALID") === false)
{
if(DEBUGTHIS == true || DEBUGTHIS == 1)
{
error_log(date('[Y-m-d H:i e] '). "res NOT Verified - Value is INVALID - res: ". $checkForVerified . "/". $res . PHP_EOL, 3, LOG_FILE);
}
}else{
if(DEBUGTHIS == true || DEBUGTHIS == 1)
{
error_log(date('[Y-m-d H:i e] '). "res is NOT Verified and is not INVALID: ". $checkForVerified . "/" . $res . PHP_EOL, 3, LOG_FILE);
}
}//close else if VERIFIED OR INVALID res
if( DEBUGTHIS == true || DEBUGTHIS == 1 && empty($payment_status) )
{
error_log(date('[Y-m-d H:i e] '). "Ended Process - Verified and Payment process skipped no data to check: ". PHP_EOL, 3, LOG_FILE);
}//close if
die('OK');