I have been spending some hours using the PayPal IPN and I can't get it to update the database when the status = 'Completed'.
I know there are a million questions about this, but I just could not figure it out. I guess everyone has a different problem.
I got a part of the script from the interwebs as I'm not that familiar with working with IPN's. Allow me to share my current code (I greyed out unimportant parts of the code):
<?php
// Connect my my own database and start the session that has the ID of the current account user
session_start();
include("connection.php");
/* Greying out
// 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);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
// STEP 2: Post IPN data back to paypal to validate
$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr'); // change to [...]sandbox.paypal[...] when using sandbox to test
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);
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');
if( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
*/
// STEP 3: Inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
// check whether 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
// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
if ($_POST['mc_gross'] != NULL)
$payment_amount = $_POST['mc_gross'];
else
$payment_amount = $_POST['mc_gross1'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
$custom = $_POST['custom'];
if($payment_status == "Completed") {
if(array_key_exists("id", $_COOKIE) AND $_COOKIE['id']) {
$_SESSION["id"] = $_COOKIE["id"];
}
if(array_key_exists("id", $_SESSION) AND $_SESSION['id']) {
// Update plan and due date to database
$id = $_SESSION['id'];
$due = date('Y-m-d', strtotime('+1 month'));
$query = "UPDATE users SET plan = 'paid' , due_date = '".mysqli_real_escape_string($link, $due)."' WHERE id = ".$id." LIMIT 1";
$result = mysqli_query($link, $query);
}
}
} else if (strcmp ($res, "INVALID") == 0) {
// log for manual investigation
}
?>
I have the whole sandbox environment setup. I checked the IPN history, and all the IPN's have a delivery status of 'Sent' and a HTTP response of 200. However, my database is not updated. I tried putting the MySQL update query outside the 'Completed' check, but that didn't do anything in my database either.
Any help would be highly appreciated,
Nathan
Save PayPal transaction id in your Database column and try to update using your db using your saved transaction ID. Cookies - session are not preferable while using IPN operation.
Could you replace below code with your VERIFIED condition code
(code under if (strcmp ($res, "VERIFIED") == 0){}):
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
if ($_POST['mc_gross'] != NULL)
$payment_amount = $_POST['mc_gross'];
else
$payment_amount = $_POST['mc_gross1'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
$custom = $_POST['custom'];
if($payment_status == "Completed") {
$due = date('Y-m-d', strtotime('+1 month'));
$query = "UPDATE users SET plan = 'paid' , due_date = '".mysqli_real_escape_string($link, $due)."' WHERE txn_id = '".$txn_id."'";
$result = mysqli_query($link, $query);
}
I hope above will solve your issue!