View Full Version : Paypal IPN problems

04-27-2012, 01:49 PM
Hey Guys,
Im having trouble with a paypal IPN script,
origionally , it was passing all the informationt to paypal
and then entering the transaction into the database once complete.

This worked fine, i then decided that i wanted to pass the session id
as a hidden field to paypal and then "update" an already existing entry in the database by the session id.

this way all the users info could be logged before he/she went to paypal.

how ever i can not seem to get this to work, am i write in thinking that this is possible?

I would REALLY appreciate any help anybody can provide.

<form class="paypal" action="" method="post" id="paypal_form" target="_blank">
<input type="hidden" name="cmd" value="_xclick" />
<input type="hidden" name="no_note" value="1" />
<input type="hidden" name="lc" value="UK" />
<input type="hidden" name="currency_code" value="GBP" />
<input type="hidden" name="bn" value="PP-BuyNowBF:btn_buynow_LG.gif:NonHostedGuest" />
<input type="hidden" name="first_name" value="<? echo $forename ; ?>" />
<input type="hidden" name="address_street" value="<? echo $address ; ?>" />
<input type="hidden" name="address_zip" value="<? echo $postcode ; ?>" />
<input type="hidden" name="last_name" value="<? echo $surname ; ?>" />
<input type="hidden" name="payer_email" value="<? echo $email ; ?>" />
<input type="hidden" name="custom" value="<? echo $key ; ?>" />
<input type="hidden" name="item_number" value="1" / >
<input type="submit" value="Submit Payment"/>

I Think the problem could be that my sql code is incorrect.


function updatePayments($data){
global $link;

$sql = mysql_query("UPDATE payments SET txnid='".$data['txn_id']."' , payment_amount='".$data['payment_amount']."' , payment_status='$".$data['payment_status']."' , itemid='".$data['item_number']."', createdtime='".date("Y-m-d H:i:s")."' , email='".$data['payer_email']."', session='".$data['key']."' WHERE session='".$data['key']."'") ;

return mysql_insert_id($link);

Any pointers would be massivley appreciated , been trying to fix this all night!

04-27-2012, 01:51 PM
Thanks in advance!

04-27-2012, 03:06 PM
I don't see the point of sending the user's personal details (name, address etc) to PayPal, even as pass through variables because PayPal doesn't need all that info at all. And if the personal details are hijacked in transit by some remote chance by a malicious hacker then you might even face legal liabilities.

I would suggest that when the user clicks your checkout button, you first create an order number in your database and then present a form to the user that collects their personal details and their payment method (credit card, PayPal, direct credit or whatever) . You then store their order number, personal details and shopping cart contents in your database before anything even goes to PayPal. Then if they selected credit card or PayPal as their payment option, you send the order number and shopping cart contents to PayPal to handle the online payment.

When you receive the verified notice at your IPN script, that means the user completed the payment for the order number and so you can update the payment status in your database for the order number you received from PayPal in the IPN data and organise the delivery of the goods and/or services.

After a set period of time (you decide how long) if you don't receive an IPN payment confirmation from PayPal, you can delete from your database the details for the order number you took at the checkout form because you can assume the user never went through with the payment at PayPal.

This is what i am trying to achieve (storeing the users details prior and updating after payment is completed, if its not then delete from database)

and i aggree about passing the users details, i supposes its not really needed.

i will remove them from the form , do you have any idea why the update is not working?

04-30-2012, 02:33 PM
I have set the script so all information stores before the user goes to paypal , a unique is created and then the idea was to pass that to paypal as custom and then update by that feild.

however it dose not seem to update, i just cant figure it out.

04-30-2012, 02:55 PM
you need to see the error that mysql is giving you (if any) to help debug...

$sql="UPDATE `payments` SET etc etc";
mysql_query($sql)or die($sql.' '.mysql_error());

if your query is failing the above should tell you why, just remember to remove that before production use, if the above gives you no output then print_r($data) at the start of your function to make sure its actually getting called.

05-01-2012, 01:10 PM
This is what i am trying to achieve (storeing the users details prior and updating after payment is completed, if its not then delete from database)

and i aggree about passing the users details, i supposes its not really needed.

i will remove them from the form , do you have any idea why the update is not working?

There is no need to remove the users details from the form - you may need them in the future. Just don't transmit them to paypal.

Also I wouldn't delete failed purchases from your database. Depending on your country there may be laws regarding the storage of financial transactions (completed and failed). In the UK you have to keep these records for 6 years for audit purposes. Deleting them will serve you no purpose if a customer emails you complaining that their order hasn't been processed either - you'll have no records of it and could have received their money with no idea who it's from. At that point your customer will accuse you of being a theif etc.

Keep the records but don't transmit more than is necessary to paypal.

05-02-2012, 05:23 PM
Ill paste the entire script below , its in two parts, payments.php & functions.php

i would GREATLY appeciate any help anybody could give me , i have a website thats been waiting to go live for a week because i cant figure this out :/


// Database variables
$host = "localhost"; //database location
$user = ""; //database username
$pass = ""; //database password
$db_name = ""; //database name

// PayPal settings
$paypal_email = 'paypal@example.com';
$return_url = 'http://example.com/payment-successful.htm';
$cancel_url = 'http://example.com/payment-cancelled.htm';
$notify_url = 'http://example.com/paypal/payments.php';

$item_name = 'Test Item';
$item_amount = 5.00;

// Include Functions

//Database Connection
$link = mysql_connect($host, $user, $pass);

// Check if paypal request or response
if (!isset($_POST["txn_id"]) && !isset($_POST["txn_type"])){

// Firstly Append paypal account to querystring
$querystring .= "?business=".urlencode($paypal_email)."&";

// Append amount& currency () to quersytring so it cannot be edited in html

//The item name and amount can be brought in dynamically by querying the $_POST['item_number'] variable.
$querystring .= "item_name=".urlencode($item_name)."&";
$querystring .= "amount=".urlencode($item_amount)."&";

//loop for posted values and append to querystring
foreach($_POST as $key => $value){
$value = urlencode(stripslashes($value));
$querystring .= "$key=$value&";

// Append paypal return addresses
$querystring .= "return=".urlencode(stripslashes($return_url))."&";
$querystring .= "cancel_return=".urlencode(stripslashes($cancel_url))."&";
$querystring .= "notify_url=".urlencode($notify_url);

// Append querystring with custom field
//$querystring .= "&custom=".USERID;

// Redirect to paypal IPN


// Response from Paypal

// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$value = preg_replace('/(.*[^%^0^D])(%0A)(.*)/i','${1}%0D%0A${3}',$value);// IPN fix
$req .= "&$key=$value";

// assign posted variables to local variables
$data['item_name'] = $_POST['item_name'];
$data['item_number'] = $_POST['item_number'];
$data['payment_status'] = $_POST['payment_status'];
$data['payment_amount'] = $_POST['mc_gross'];
$data['payment_currency'] = $_POST['mc_currency'];
$data['txn_id'] = $_POST['txn_id'];
$data['receiver_email'] = $_POST['receiver_email'];
$data['payer_email'] = $_POST['payer_email'];
$data['custom'] = $_POST['custom'];

// post back to PayPal system to validate
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);

if (!$fp) {
} else {

fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
if (strcmp($res, "VERIFIED") == 0) {

// Used for debugging
//@mail("you@youremail.com", "PAYPAL DEBUGGING", "Verified Response<br />data = <pre>".print_r($post, true)."</pre>");

// Validate payment (Check unique txnid & correct price)
$valid_txnid = check_txnid($data['txn_id']);
$valid_price = check_price($data['payment_amount'], $data['item_number']);
if($valid_txnid && $valid_price){
$orderid = updatePayments($data);
// Payment has been made & successfully inserted into the Database
// Error inserting into DB
// E-mail admin or alert user
// Payment made but data has been changed
// E-mail admin or alert user

}else if (strcmp ($res, "INVALID") == 0) {

// E-mail admin or alert user

// Used for debugging
//@mail("you@youremail.com", "PAYPAL DEBUGGING", "Invalid Response<br />data = <pre>".print_r($post, true)."</pre>");
fclose ($fp);


// functions.php
function check_txnid($tnxid){
global $link;
return true;
$valid_txnid = true;
//get result set
$sql = mysql_query("SELECT * FROM `payments` WHERE txnid = '$tnxid'", $link);
if($row = mysql_fetch_array($sql)) {
$valid_txnid = false;
return $valid_txnid;

function check_price($price, $id){
$valid_price = false;
//you could use the below to check whether the correct price has been paid for the product

$sql = mysql_query("SELECT amount FROM `products` WHERE id = '$id'");
if (mysql_numrows($sql) != 0) {
while ($row = mysql_fetch_array($sql)) {
$num = (float)$row['amount'];
if($num == $price){
$valid_price = true;
return $valid_price;
return true;

function updatePayments($data){
global $link;
$sql = mysql_query("INSERT INTO `payments` (txnid, payment_amount, payment_status, itemid, createdtime) VALUES (
'".$data['txn_id']."' ,
'".$data['payment_amount']."' ,
'".$data['payment_status']."' ,
'".$data['item_number']."' ,
'".date("Y-m-d H:i:s")."'
)", $link);
return mysql_insert_id($link);

that all works GREAT , however , when i came to try and alter it...to update the database instead of updating , i couldnt get it to work.

i tried:


function updatePayments($data){
global $link;

$sql = mysql_query("UPDATE payments SET payment_status='complete' , createdtime='".date("Y-m-d H:i:s")."' , WHERE uniqueid=''".$data['custom']."'") ;
return mysql_insert_id($link);

05-02-2012, 05:31 PM
you have an extra single quote in your $sql WHERE uniqueid=''".$d and an unneeded comma b4 the WHERE statement

if you are in a rush you should heed the advice already given and show us the actual error you are getting..... the code posted earlier would have shown you these errors

$q="UPDATE `payments` SET `payment_status`= 'complete' , `createdtime`='".date("Y-m-d H:i:s")."' WHERE `uniqueid`='{$data['custom']}'";
$sql = mysql_query($q) or die($sql.'<br />'.mysql_error());

05-02-2012, 05:54 PM
no error comes back from the script.