Archived

This topic is now archived and is closed to further replies.

Paypal IPN/Auto return payment failed solution

0 posts in this topic

Posted · Report post

as many of you paypal standard/IPN users, I have experienced the same infamous "your oder failed" error when customer is redirected back to my store. The root cause is the timming - sometimes paypal calls IPN.php after paypal redirects customer to the confirmed.php. Another problem is, if customer pay it via echeck, even if ipn.php is called first, the order status will still be pending, thus customer will see "your order failed" too.

Long story in short, I have found a solution for it.

Here is how to:

you only need to modify confirmed.inc.php in includes/content directory.

find:

$cart = new cart();




after that, add:




///////////////////////////

// Added by paypal auto return fix

///////////////////////////

$logflag = TRUE;

///////////////////////////

// End

///////////////////////////




find:




################################################################################

############

// Following lines added for Sir William's PayPal AutoReturn Fix

} elseif(isset($_GET['tx']) && isset($_GET['st'])) {

 $basket['gateway'] = "PayPal";

################################################################################

############




after that, add:




///////////////////////////

// Added by paypal auto return fix

///////////////////////////

$module = fetchDbConfig("PayPal");

///////////////////////////

// End

///////////////////////////






find:




$success = success();




after that, add:




///////////////////////////

// Added by paypal auto return fix

///////////////////////////

if ( ( $success == FALSE ) && (isset($_GET['tx']) && isset($_GET['st'])) )

{

	$success = pdtcheck();

}

////////////////////////////////

// End

////////////////////////////////




finally, add the following 2 methods at the end of the file (just before the 
?>
):




////////////////////////////////

// Added by paypal auto return fix

////////////////////////////////

function pdtcheck()

{

	global $db, $glob, $module, $basket;

	// read the post from PayPal system and add 'cmd'

	$req = 'cmd=_notify-synch';



	$tx_token = $_GET['tx'];

	logMsg( "" );

	logMsg( "Using PDT to check order status for tx:".$tx_token );

	$auth_token = "this is provied by paypal - check your paypal PDT config";

	$req .= "&tx=$tx_token&at=$auth_token";



	// 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 ('www.sandbox.paypal.com', 80, $errno, $errstr, 30);

	// If possible, securely post back to paypal using HTTPS

	// Your PHP server will need to be SSL enabled

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



	if (!$fp)

	{

		// HTTP ERROR

		logMsg ("HTTP ERROR");

	}

	else

	{

		fputs ($fp, $header . $req);

		// read the body data

		$res = '';

		$headerdone = false;

		while (!feof($fp))

		{

			$line = fgets ($fp, 1024);

				if (strcmp($line, "\r\n") == 0)

				{

					// read the header

					$headerdone = true;

				}

				else if ($headerdone)

				{

					// header has been read. now read the contents

					$res .= $line;

				}

		}



		// parse the data

		$lines = explode("\n", $res);

		$keyarray = array();

		if (strcmp ($lines[0], "SUCCESS") == 0)

		{

			for ($i=1; $i<count($lines);$i++)

			{

				list($key,$val) = explode("=", $lines[$i]);

				$keyarray[urldecode($key)] = urldecode($val);

			}



			/**

			 * Check invoie, amount and receiver_email are correct

			 */

			$amount = $keyarray['payment_gross'];

			$invoiceId = $keyarray['invoice'];

			$receiver_email = $keyarray['receiver_email'];

			$sqlstat = "SELECT * FROM ".$glob['dbprefix']."CubeCart_order_sum WHERE cart_order_id = ".$db->mySQLSafe($invoiceId);

			$result = $db->select( $sqlstat );

			if ( ($result[0]['prod_total'] == $amount ) && ( strcmp( $module['email'], $receiver_email ) == 0 ) )

			{

				logMsg ("Verify Success");

				return TRUE;

			}

			else

			{

				logMsg ( "Verify Failed, Paypal response follows:" );

				logMsg ( "		Amount = " . $amount );

			  logMsg ( "	   Invoice = " . $invoiceId );

			  logMsg ( "Receiver Email = " . $receiver_email );

				return FALSE;

			}

		}

		else

		{

			logMsg ( "Payment Failed, Paypal response follows:" );

			logMsg ( $res );

			return FALSE;

		}

	}

	fclose ($fp);

}



function logmsg( $msg )

{

	global $logflag;

	if ( $logflag == FALSE )

	{

		return;

	}

	$today = date("Y-M-d");

	$myFile = "/location for my log files/".date("Y-M-d").".log";

	$fh = fopen($myFile, 'a') or die("can't open file");

	$stringData = date("[Y/M/d, G:i:s] ").$msg."\n";

	fwrite($fh, $stringData);

	fclose($fh);

}

////////////////////////////////

// End

////////////////////////////////






Let me explain how it works:



when user is transferred back to the confirmed.php, success() method is called first.  If IPN is called first, and if the status becomes "process", success() will return TRUE, then the payment is successful.



If IPN is not called yet, or customer sent an echeck, the status is pending, success() returns FALSE, then checkPDT() is called.



checkPDT() sends a request to paypal server with tx id received when paypal calls confirmed.php, then paypal sends back the transcation details, including invoice number, totoal amount and more.  So, in checkPDT() method, we do a db query, by using the invoice id, amount received from paypal and check wheter they matches, if everything is ok, return TRUE, otherwise, return FALSE.



If you add the above two methods to your file, make sure to replace the auth_token with the ones provided by paypal.  I am using sandbox for test, don't forget to change it back to www.paypal.com for production.  Also, you need to change the log location.  You can just create a directoy inside your store, give it a wired name, such as 
.$ba_ufdkj

, and give it a 777. The reason for a wired name is, people cannot guess it. oh, also password protect the log directory...it will block all http accesses.

I hope this helps :-)

Share this post


Link to post
Share on other sites

Posted · Report post

Nice one!!

Share this post


Link to post
Share on other sites

Posted · Report post

I cannot believe nobody is interested in the fix! finally I got a PM from acheio asking the log dir.

The log dir can be anywhere in your root, such as in www or public_html directory. However, it must have correct prrmissions, 777 should be ok

I cannot believe you PAYPAL users do not have this problem.

Share this post


Link to post
Share on other sites

Posted · Report post

Hi Go,

It may be that many have used the code and didn't think to reply afterwards. I intend to try it myself and thank you in advance! :rolly:

Share this post


Link to post
Share on other sites

Posted · Report post

Looks beautimus. :D

I've had the problem less than 1% of the time, but some people evidently have it a LOT more. I have long thought it was due to timing/latency issues, but hadn't thought of a good fix for it yet. This is indeed a welcomed implementation. I of course want to do some testing, but if all checks out, I'll recommend inclusion into the CubeCart code base....with your permission of course. :D

:D

Share this post


Link to post
Share on other sites

Posted · Report post

I to rarely got this message come back to me but i did have 2 or 3 times and i have been testing this on my site for about 7 days now and as of yet no one has complained.

fingers crossed.

Share this post


Link to post
Share on other sites

Posted · Report post

Hi

I have just tried this for Paypal follwed exactly step by step and I still get this error:-

"Confirmation Screen

Basket » Address » Payment » Complete

Sorry, your order failed!

You can attempt to purchase your basket contents again below

"

The Log file was created but was blank,the Paypal token was also input in the script and the log file path was setcorrectly.

Any ideas what went wrong.

Thanks

Nizam

as many of you paypal standard/IPN users, I have experienced the same infamous "your oder failed" error when customer is redirected back to my store. The root cause is the timming - sometimes paypal calls IPN.php after paypal redirects customer to the confirmed.php. Another problem is, if customer pay it via echeck, even if ipn.php is called first, the order status will still be pending, thus customer will see "your order failed" too.

Long story in short, I have found a solution for it.

Here is how to:

you only need to modify confirmed.inc.php in includes/content directory.

find:

$cart = new cart();




after that, add:




///////////////////////////

// Added by paypal auto return fix

///////////////////////////

$logflag = TRUE;

///////////////////////////

// End

///////////////////////////




find:




################################################################################

############

// Following lines added for Sir William's PayPal AutoReturn Fix

} elseif(isset($_GET['tx']) && isset($_GET['st'])) {

 $basket['gateway'] = "PayPal";

################################################################################

############




after that, add:




///////////////////////////

// Added by paypal auto return fix

///////////////////////////

$module = fetchDbConfig("PayPal");

///////////////////////////

// End

///////////////////////////






find:




$success = success();




after that, add:




///////////////////////////

// Added by paypal auto return fix

///////////////////////////

if ( ( $success == FALSE ) && (isset($_GET['tx']) && isset($_GET['st'])) )

{

	$success = pdtcheck();

}

////////////////////////////////

// End

////////////////////////////////




finally, add the following 2 methods at the end of the file (just before the 
?>
):




////////////////////////////////

// Added by paypal auto return fix

////////////////////////////////

function pdtcheck()

{

	global $db, $glob, $module, $basket;

	// read the post from PayPal system and add 'cmd'

	$req = 'cmd=_notify-synch';



	$tx_token = $_GET['tx'];

	logMsg( "" );

	logMsg( "Using PDT to check order status for tx:".$tx_token );

	$auth_token = "this is provied by paypal - check your paypal PDT config";

	$req .= "&tx=$tx_token&at=$auth_token";



	// 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 ('www.sandbox.paypal.com', 80, $errno, $errstr, 30);

	// If possible, securely post back to paypal using HTTPS

	// Your PHP server will need to be SSL enabled

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



	if (!$fp)

	{

		// HTTP ERROR

		logMsg ("HTTP ERROR");

	}

	else

	{

		fputs ($fp, $header . $req);

		// read the body data

		$res = '';

		$headerdone = false;

		while (!feof($fp))

		{

			$line = fgets ($fp, 1024);

				if (strcmp($line, "\r\n") == 0)

				{

					// read the header

					$headerdone = true;

				}

				else if ($headerdone)

				{

					// header has been read. now read the contents

					$res .= $line;

				}

		}



		// parse the data

		$lines = explode("\n", $res);

		$keyarray = array();

		if (strcmp ($lines[0], "SUCCESS") == 0)

		{

			for ($i=1; $i<count($lines);$i++)

			{

				list($key,$val) = explode("=", $lines[$i]);

				$keyarray[urldecode($key)] = urldecode($val);

			}



			/**

			 * Check invoie, amount and receiver_email are correct

			 */

			$amount = $keyarray['payment_gross'];

			$invoiceId = $keyarray['invoice'];

			$receiver_email = $keyarray['receiver_email'];

			$sqlstat = "SELECT * FROM ".$glob['dbprefix']."CubeCart_order_sum WHERE cart_order_id = ".$db->mySQLSafe($invoiceId);

			$result = $db->select( $sqlstat );

			if ( ($result[0]['prod_total'] == $amount ) && ( strcmp( $module['email'], $receiver_email ) == 0 ) )

			{

				logMsg ("Verify Success");

				return TRUE;

			}

			else

			{

				logMsg ( "Verify Failed, Paypal response follows:" );

				logMsg ( "		Amount = " . $amount );

			  logMsg ( "	   Invoice = " . $invoiceId );

			  logMsg ( "Receiver Email = " . $receiver_email );

				return FALSE;

			}

		}

		else

		{

			logMsg ( "Payment Failed, Paypal response follows:" );

			logMsg ( $res );

			return FALSE;

		}

	}

	fclose ($fp);

}



function logmsg( $msg )

{

	global $logflag;

	if ( $logflag == FALSE )

	{

		return;

	}

	$today = date("Y-M-d");

	$myFile = "/location for my log files/".date("Y-M-d").".log";

	$fh = fopen($myFile, 'a') or die("can't open file");

	$stringData = date("[Y/M/d, G:i:s] ").$msg."\n";

	fwrite($fh, $stringData);

	fclose($fh);

}

////////////////////////////////

// End

////////////////////////////////






Let me explain how it works:



when user is transferred back to the confirmed.php, success() method is called first.  If IPN is called first, and if the status becomes "process", success() will return TRUE, then the payment is successful.



If IPN is not called yet, or customer sent an echeck, the status is pending, success() returns FALSE, then checkPDT() is called.



checkPDT() sends a request to paypal server with tx id received when paypal calls confirmed.php, then paypal sends back the transcation details, including invoice number, totoal amount and more.  So, in checkPDT() method, we do a db query, by using the invoice id, amount received from paypal and check wheter they matches, if everything is ok, return TRUE, otherwise, return FALSE.



If you add the above two methods to your file, make sure to replace the auth_token with the ones provided by paypal.  I am using sandbox for test, don't forget to change it back to www.paypal.com for production.  Also, you need to change the log location.  You can just create a directoy inside your store, give it a wired name, such as 
.$ba_ufdkj

, and give it a 777. The reason for a wired name is, people cannot guess it. oh, also password protect the log directory...it will block all http accesses.

I hope this helps :-)

Share this post


Link to post
Share on other sites

Posted · Report post

could you paste the code here? ofcourse remove sensitive parts.

Hi

I have just tried this for Paypal follwed exactly step by step and I still get this error:-

"Confirmation Screen

Basket » Address » Payment » Complete

Sorry, your order failed!

You can attempt to purchase your basket contents again below

"

The Log file was created but was blank,the Paypal token was also input in the script and the log file path was setcorrectly.

Any ideas what went wrong.

Thanks

Nizam

Looks beautimus. :)

I've had the problem less than 1% of the time, but some people evidently have it a LOT more. I have long thought it was due to timing/latency issues, but hadn't thought of a good fix for it yet. This is indeed a welcomed implementation. I of course want to do some testing, but if all checks out, I'll recommend inclusion into the CubeCart code base....with your permission of course. :D

:)

:D

is there any discount on CC? I have another mod for order status check, not sure if anyone is interested

:D

Share this post


Link to post
Share on other sites

Posted · Report post

heheh...that's completely up to Brooky. But we're always looking for good code/mods. :)

:)

Share this post


Link to post
Share on other sites

Posted · Report post

Thanks for your reply. I was hoping someone would solve it. In Version 3.06 I had applied Sir Williams patch and it was working perfect with a 0.01 cent live transaction, however when I upgraded to 3.07-1pl I am getting error "Sorry order fail" , 'pending' inspite of money being credited into Paypal account.

Then I applied your fix and hoped that this would not happen but it happened again.

Well here is the code:-

"

<?php

/*

+--------------------------------------------------------------------------

| CubeCart v3.0.7-pl1

| ========================================

| by Alistair Brookbanks

| CubeCart is a Trade Mark of Devellion Limited

| Copyright Devellion Limited 2005 - 2006. All rights reserved.

| Devellion Limited,

| Westfield Lodge,

| Westland Green,

| Little Hadham,

| Nr Ware, HERTS.

| SG11 2AL

| UNITED KINGDOM

| http://www.devellion.com

| UK Private Limited Company No. 5323904

| ========================================

| Web: http://www.cubecart.com

| Date: Monday, 2nd January 2006

| Email: info (at) cubecart (dot) com

| License Type: CubeCart is NOT Open Source Software and Limitations Apply

| Licence Info: http://www.cubecart.com/site/faq/license.php

+--------------------------------------------------------------------------

| confirmed.inc.php

| ========================================

| Order Confirmation

+--------------------------------------------------------------------------

*/

if (ereg(".inc.php",$HTTP_SERVER_VARS['PHP_SELF'])) {

echo "<html>\r\n<head>\r\n<title>Forbidden 403</title>\r\n</head>\r\n<body><h3>Forbidden 403</h3>\r\nThe document you are requesting is forbidden.\r\n</body>\r\n</html>";

exit;

}

require_once("classes/cart.php");

$cart = new cart();

///////////////////////////

// Added by paypal auto return fix

///////////////////////////

$logflag = TRUE;

///////////////////////////

// End

///////////////////////////

$basket = $cart->cartContents($ccUserData[0]['basket']);

// WORK OUT IS THE ORDER WAS SUCCESSFULL OR NOT :rolly:

// 1. Include gateway file

// Override basket value as fix for some gateways

if(isset($_GET['pg']) && !empty($_GET['pg'])){

$pg = base64_decode($_GET['pg']);

if(ereg("Authorize|WorldPay|Protx|SECPay|BluePay",$pg)){

$basket['gateway'] = $pg;

}

################################################################################

############

// Following lines added for Sir William's PayPal AutoReturn Fix

} elseif(isset($_GET['tx']) && isset($_GET['st'])) {

$basket['gateway'] = "PayPal";

################################################################################

############

///////////////////////////

// Added by paypal auto return fix

///////////////////////////

$module = fetchDbConfig("PayPal");

///////////////////////////

// End

///////////////////////////

} elseif(!isset($basket['gateway'])){

echo "Error: No payment gateway variable is set!";

exit;

}

include("modules/gateway/".$basket['gateway']."/transfer.inc.php");

// 2. Include function which returns ture or false

$success = success();

///////////////////////////

// Added by paypal auto return fix

///////////////////////////

if ( ( $success == FALSE ) && (isset($_GET['tx']) && isset($_GET['st'])) )

{

$success = pdtcheck();

}

////////////////////////////////

// End

////////////////////////////////

$confirmation = new XTemplate ("skins/".$config['skinDir']."/styleTemplates/content/confirmed.tpl");

$confirmation->assign("LANG_CONFIRMATION_SCREEN",$lang['front']['confirmed']['confirmation_screen']);

$confirmation->assign("LANG_CART",$lang['front']['confirmed']['cart']);

$confirmation->assign("LANG_ADDRESS",$lang['front']['confirmed']['address']);

$confirmation->assign("LANG_PAYMENT",$lang['front']['confirmed']['payment']);

$confirmation->assign("LANG_COMPLETE",$lang['front']['confirmed']['complete']);

if($success == TRUE){

if($stateUpdate == TRUE){

$cart_order_id = $basket['cart_order_id'];

include_once("includes/orderSuccess.inc.php");

}

$confirmation->assign("LANG_ORDER_SUCCESSFUL",$lang['front']['confirmed']['order_success']);

// add affilate tracking code/module

$affiliateModule = $db->select("SELECT status, folder, `default` FROM ".$glob['dbprefix']."CubeCart_Modules WHERE module='affiliate' AND status = 1");

if($affiliateModule == TRUE) {

for($i=0; $i<count($affiliateModule); $i++){

if($affiliateModule[$i]['status']==1){

include("modules/affiliate/".$affiliateModule[$i]['folder']."/tracker.inc.php");

// VARS AVAILABLE

// Order Id Number $basket['cart_order_id']

// Order Total $order[0]['prod_total']

$confirmation->assign("AFFILIATE_IMG_TRACK",$affCode);

$confirmation->parse("confirmation.session_true.order_success.aff_track");

}

}

}

$confirmation->parse("confirmation.session_true.order_success");

// empty basket & other session data

$basket = $cart->unsetVar("conts");

$basket = $cart->unsetVar("delInf");

$basket = $cart->unsetVar("cart_order_id");

$basket = $cart->unsetVar("shipCost");

$basket = $cart->unsetVar("subTotal");

$basket = $cart->unsetVar("tax");

$basket = $cart->unsetVar("shipCost");

$basket = $cart->unsetVar("grandTotal");

$basket = $cart->unsetVar("customer_comments");

$basket = $cart->unsetVar("counted");

$basket = $cart->unsetVar("shipMethod");

} else {

$confirmation->assign("LANG_ORDER_FAILED",$lang['front']['confirmed']['order_fail']);

$confirmation->assign("LANG_ORDER_RETRY",$lang['front']['confirmed']['try_again_desc']);

$confirmation->assign("LANG_RETRY_BUTTON",$lang['front']['confirmed']['try_again']);

$confirmation->parse("confirmation.session_true.order_failed");

}

$confirmation->assign("LANG_LOGIN_REQUIRED",$lang['front']['confirmed']['request_login']);

if($ccUserData[0]['customer_id']>0) $confirmation->parse("confirmation.session_true");

else $confirmation->parse("confirmation.session_false");

$confirmation->parse("confirmation");

$page_content = $confirmation->text("confirmation");

////////////////////////////////

// Added by paypal auto return fix

////////////////////////////////

function pdtcheck()

{

global $db, $glob, $module, $basket;

// read the post from PayPal system and add 'cmd'

$req = 'cmd=_notify-synch';

$tx_token = $_GET['tx'];

logMsg( "" );

logMsg( "Using PDT to check order status for tx:".$tx_token );

$auth_token = "XXXXXXXXXXXXXu8UD58QnU9uqXXXXXXXX0lZXGmxy";

$req .= "&tx=$tx_token&at=$auth_token";

// 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 ('www.sandbox.paypal.com', 80, $errno, $errstr, 30);

// If possible, securely post back to paypal using HTTPS

// Your PHP server will need to be SSL enabled

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

if (!$fp)

{

// HTTP ERROR

logMsg ("HTTP ERROR");

}

else

{

fputs ($fp, $header . $req);

// read the body data

$res = '';

$headerdone = false;

while (!feof($fp))

{

$line = fgets ($fp, 1024);

if (strcmp($line, "\r\n") == 0)

{

// read the header

$headerdone = true;

}

else if ($headerdone)

{

// header has been read. now read the contents

$res .= $line;

}

}

// parse the data

$lines = explode("\n", $res);

$keyarray = array();

if (strcmp ($lines[0], "SUCCESS") == 0)

{

for ($i=1; $i<count($lines);$i++)

{

list($key,$val) = explode("=", $lines[$i]);

$keyarray[urldecode($key)] = urldecode($val);

}

/**

* Check invoie, amount and receiver_email are correct

*/

$amount = $keyarray['payment_gross'];

$invoiceId = $keyarray['invoice'];

$receiver_email = $keyarray['receiver_email'];

$sqlstat = "SELECT * FROM ".$glob['dbprefix']."CubeCart_order_sum WHERE cart_order_id = ".$db->mySQLSafe($invoiceId);

$result = $db->select( $sqlstat );

if ( ($result[0]['prod_total'] == $amount ) && ( strcmp( $module['email'], $receiver_email ) == 0 ) )

{

logMsg ("Verify Success");

return TRUE;

}

else

{

logMsg ( "Verify Failed, Paypal response follows:" );

logMsg ( " Amount = " . $amount );

logMsg ( " Invoice = " . $invoiceId );

logMsg ( "Receiver Email = " . $receiver_email );

return FALSE;

}

}

else

{

logMsg ( "Payment Failed, Paypal response follows:" );

logMsg ( $res );

return FALSE;

}

}

fclose ($fp);

}

function logmsg( $msg )

{

global $logflag;

if ( $logflag == FALSE )

{

return;

}

$today = date("Y-M-d");

$myFile = "/home/httpd/vhosts/domain.com/httpdocs/cart/logxxx/".date("Y-M-d").".log";

$fh = fopen($myFile, 'a') or die("can't open file");

$stringData = date("[Y/M/d, G:i:s] ").$msg."\n";

fwrite($fh, $stringData);

fclose($fh);

}

////////////////////////////////

// End

////////////////////////////////

?>

"

Hope you can solve thiis problem.

Thanks and goodday

Hi

I have just tried this for Paypal follwed exactly step by step and I still get this error:-

"Confirmation Screen

Basket » Address » Payment » Complete

Sorry, your order failed!

You can attempt to purchase your basket contents again below

"

The Log file was created but was blank,the Paypal token was also input in the script and the log file path was setcorrectly.

Any ideas what went wrong.

Thanks

Nizam

as many of you paypal standard/IPN users, I have experienced the same infamous "your oder failed" error when customer is redirected back to my store. The root cause is the timming - sometimes paypal calls IPN.php after paypal redirects customer to the confirmed.php. Another problem is, if customer pay it via echeck, even if ipn.php is called first, the order status will still be pending, thus customer will see "your order failed" too.

Long story in short, I have found a solution for it.

Here is how to:

you only need to modify confirmed.inc.php in includes/content directory.

find:

$cart = new cart();




after that, add:




///////////////////////////

// Added by paypal auto return fix

///////////////////////////

$logflag = TRUE;

///////////////////////////

// End

///////////////////////////




find:




################################################################################

############

// Following lines added for Sir William's PayPal AutoReturn Fix

} elseif(isset($_GET['tx']) && isset($_GET['st'])) {

 $basket['gateway'] = "PayPal";

################################################################################

############




after that, add:




///////////////////////////

// Added by paypal auto return fix

///////////////////////////

$module = fetchDbConfig("PayPal");

///////////////////////////

// End

///////////////////////////






find:




$success = success();




after that, add:




///////////////////////////

// Added by paypal auto return fix

///////////////////////////

if ( ( $success == FALSE ) && (isset($_GET['tx']) && isset($_GET['st'])) )

{

	$success = pdtcheck();

}

////////////////////////////////

// End

////////////////////////////////




finally, add the following 2 methods at the end of the file (just before the 
?>
):




////////////////////////////////

// Added by paypal auto return fix

////////////////////////////////

function pdtcheck()

{

	global $db, $glob, $module, $basket;

	// read the post from PayPal system and add 'cmd'

	$req = 'cmd=_notify-synch';



	$tx_token = $_GET['tx'];

	logMsg( "" );

	logMsg( "Using PDT to check order status for tx:".$tx_token );

	$auth_token = "this is provied by paypal - check your paypal PDT config";

	$req .= "&tx=$tx_token&at=$auth_token";



	// 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 ('www.sandbox.paypal.com', 80, $errno, $errstr, 30);

	// If possible, securely post back to paypal using HTTPS

	// Your PHP server will need to be SSL enabled

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



	if (!$fp)

	{

		// HTTP ERROR

		logMsg ("HTTP ERROR");

	}

	else

	{

		fputs ($fp, $header . $req);

		// read the body data

		$res = '';

		$headerdone = false;

		while (!feof($fp))

		{

			$line = fgets ($fp, 1024);

				if (strcmp($line, "\r\n") == 0)

				{

					// read the header

					$headerdone = true;

				}

				else if ($headerdone)

				{

					// header has been read. now read the contents

					$res .= $line;

				}

		}



		// parse the data

		$lines = explode("\n", $res);

		$keyarray = array();

		if (strcmp ($lines[0], "SUCCESS") == 0)

		{

			for ($i=1; $i<count($lines);$i++)

			{

				list($key,$val) = explode("=", $lines[$i]);

				$keyarray[urldecode($key)] = urldecode($val);

			}



			/**

			 * Check invoie, amount and receiver_email are correct

			 */

			$amount = $keyarray['payment_gross'];

			$invoiceId = $keyarray['invoice'];

			$receiver_email = $keyarray['receiver_email'];

			$sqlstat = "SELECT * FROM ".$glob['dbprefix']."CubeCart_order_sum WHERE cart_order_id = ".$db->mySQLSafe($invoiceId);

			$result = $db->select( $sqlstat );

			if ( ($result[0]['prod_total'] == $amount ) && ( strcmp( $module['email'], $receiver_email ) == 0 ) )

			{

				logMsg ("Verify Success");

				return TRUE;

			}

			else

			{

				logMsg ( "Verify Failed, Paypal response follows:" );

				logMsg ( "		Amount = " . $amount );

			  logMsg ( "	   Invoice = " . $invoiceId );

			  logMsg ( "Receiver Email = " . $receiver_email );

				return FALSE;

			}

		}

		else

		{

			logMsg ( "Payment Failed, Paypal response follows:" );

			logMsg ( $res );

			return FALSE;

		}

	}

	fclose ($fp);

}



function logmsg( $msg )

{

	global $logflag;

	if ( $logflag == FALSE )

	{

		return;

	}

	$today = date("Y-M-d");

	$myFile = "/location for my log files/".date("Y-M-d").".log";

	$fh = fopen($myFile, 'a') or die("can't open file");

	$stringData = date("[Y/M/d, G:i:s] ").$msg."\n";

	fwrite($fh, $stringData);

	fclose($fh);

}

////////////////////////////////

// End

////////////////////////////////






Let me explain how it works:



when user is transferred back to the confirmed.php, success() method is called first.  If IPN is called first, and if the status becomes "process", success() will return TRUE, then the payment is successful.



If IPN is not called yet, or customer sent an echeck, the status is pending, success() returns FALSE, then checkPDT() is called.



checkPDT() sends a request to paypal server with tx id received when paypal calls confirmed.php, then paypal sends back the transcation details, including invoice number, totoal amount and more.  So, in checkPDT() method, we do a db query, by using the invoice id, amount received from paypal and check wheter they matches, if everything is ok, return TRUE, otherwise, return FALSE.



If you add the above two methods to your file, make sure to replace the auth_token with the ones provided by paypal.  I am using sandbox for test, don't forget to change it back to www.paypal.com for production.  Also, you need to change the log location.  You can just create a directoy inside your store, give it a wired name, such as 
.$ba_ufdkj

, and give it a 777. The reason for a wired name is, people cannot guess it. oh, also password protect the log directory...it will block all http accesses.

I hope this helps :-)

Share this post


Link to post
Share on other sites

Posted · Report post

when I upgraded to 3.07-1pl I am getting error "Sorry order fail" , 'pending' inspite of money being credited into Paypal account.

ok... it seems your IPN is not working at all. The first thing you need to do is, make sure IPN works. Don't worry about 'your order failed' now error, go to admin order page, if your order's status is 'Processing' after you send the payment (wait a minute or 2 or 5 minutes at most), then your IPN is working, otherwise, your IPN is not working.

After you fix the IPN problem, then try to apply my patch.

Share this post


Link to post
Share on other sites

Posted · Report post

Thanks for your kind help.

I realised that I had not replaced my IPN file in the module folder with the new version 3.07-1lp. My server was still having the 3.07 version. After I replaced this my IPN worked and I even got 'Your order was successful' . But I had to do a live transaction of 0.01 cents.It does not work with Sandbox. It was showing 'processing' and 'Success'.

Since you also had a fix for echeck I decided to put in your fix in confirmed.inc file. It still worked well and I got 'Your order was successful' . One thing more is there a log file created in the Log folder if the order is successful?. I checked my Log folder and there was no log file in it.

Thanks for your help.

when I upgraded to 3.07-1pl I am getting error "Sorry order fail" , 'pending' inspite of money being credited into Paypal account.

ok... it seems your IPN is not working at all. The first thing you need to do is, make sure IPN works. Don't worry about 'your order failed' now error, go to admin order page, if your order's status is 'Processing' after you send the payment (wait a minute or 2 or 5 minutes at most), then your IPN is working, otherwise, your IPN is not working.

After you fix the IPN problem, then try to apply my patch.

Share this post


Link to post
Share on other sites

Posted · Report post

The log will be created only if the normall check fails, e.g. only if checkPDT() is being called.

The log doesn't appear in your directoy, it means the original check was successful, so my checkPDT() is not called at all.

Thanks for your kind help.

I realised that I had not replaced my IPN file in the module folder with the new version 3.07-1lp. My server was still having the 3.07 version. After I replaced this my IPN worked and I even got 'Your order was successful' . But I had to do a live transaction of 0.01 cents.It does not work with Sandbox. It was showing 'processing' and 'Success'.

Since you also had a fix for echeck I decided to put in your fix in confirmed.inc file. It still worked well and I got 'Your order was successful' . One thing more is there a log file created in the Log folder if the order is successful?. I checked my Log folder and there was no log file in it.

Thanks for your help.

when I upgraded to 3.07-1pl I am getting error "Sorry order fail" , 'pending' inspite of money being credited into Paypal account.

ok... it seems your IPN is not working at all. The first thing you need to do is, make sure IPN works. Don't worry about 'your order failed' now error, go to admin order page, if your order's status is 'Processing' after you send the payment (wait a minute or 2 or 5 minutes at most), then your IPN is working, otherwise, your IPN is not working.

After you fix the IPN problem, then try to apply my patch.

Share this post


Link to post
Share on other sites

Posted · Report post

Hi,

Is this fixed in v3.0.8? I am testing the cart with PayPal Sandbox. The order status for the client was changed to Processing but the PDT page gave the error -- your oder failed. Will this fix correct this issue?

Best Regards

Share this post


Link to post
Share on other sites

Posted · Report post

Sandbox = Bad..... Make a $0.01 product and buy it with the live PayPal. Give it a shot and see how it goes.

B)

Share this post


Link to post
Share on other sites

Posted · Report post

Sandbox = Bad..... Make a $0.01 product and buy it with the live PayPal. Give it a shot and see how it goes.

;)

Alright I will give it a try. Thanks :)

Share this post


Link to post
Share on other sites

Posted · Report post

Thank you so much for fixing this! It's been driving me nuts! I set it up with my 3.08 site and it works fine.

Share this post


Link to post
Share on other sites

Posted · Report post

I don't know if we are talking about the same problem here, but mine is slightly different. I return from PayPal to my confirmation screen ok, however the confirm screen displays the message " You must login to view this page". Will this modification correct that problem?

THank You,

Klaus Cook

Houston, Texas

Share this post


Link to post
Share on other sites

Posted · Report post

Hi there- I'm having this problem as well. I applied your code to my confirmed.inc.php page, and it shows up as "You need to login to view this page". When I re-login, the failure notice shows up, along with this:

Warning: fsockopen(): no SSL support in this build in /home/content/i/n/q/inquartashop/html/store/includes/content/confirmed.inc.php on line 176

Warning: fsockopen(): unable to connect to www.paypal.com:443 in /home/content/i/n/q/inquartashop/html/store/includes/content/confirmed.inc.php on line 176

Warning: fclose(): supplied argument is not a valid stream resource in /home/content/i/n/q/inquartashop/html/store/includes/content/confirmed.inc.php on line 244

The only changes I made to the code was to put in my PayPal PDT code into $auth_token, commenting out $fp = fsockopen ('www.sandbox.paypal.com', 80, $errno, $errstr, 30); and uncommenting $fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);.

I sure could use some insight here- I really appreciate all the knowledge I've mooched off you guys already. Thanks.

:D

Share this post


Link to post
Share on other sites

Posted · Report post

My Paypal IPN works perfectly, but I also get the "You must login to view this page" error when returning to the store rather than a confirm message.

The customer gets the email and the order seems fine.

thanks

Mike

My Paypal IPN works perfectly, but I also get the "You must login to view this page" error when returning to the store rather than a confirm message.

The customer gets the email and the order seems fine.

thanks

Mike

And I have just got it to work by making sure that all the return addresses in Paypal have www in the store url, and that global_inc.php has www in the store url as well.

It then works absolutely fine!

Mike

Share this post


Link to post
Share on other sites

Posted · Report post

I just noticed I never posted a thank for this mod!

THANK YOU go77306!

I actually installed this months ago and it works great.

Ahh now i remember why I never posted, because I was not sure about how the log file thing would work and I was worried if I did not have it set up right then it would give some kind of fatal error during my customers checkout process. So ever since I just '//' out the code that writes the log file.

Maybe I will go back in and enable it. Hopefully I will get it right.

Thanks again though for the great IPN fix.

-Tim

Share this post


Link to post
Share on other sites

Posted · Report post

Where do I find the PayPal auth_token? I logged into my profile, but could not find it anywhere.

Share this post


Link to post
Share on other sites

Posted · Report post

Many thanks for this posting, I tested my PayPal checkout for the first time today and received the your order failed message on my first transaction.

I applied the patch as directed in this post and now it works a treat. Well done and thank you.

Regards

John

Share this post


Link to post
Share on other sites

Posted · Report post

Ok,

I just tried testing the PayPal Standard & IPN gateway that I've enabled but both times it did not revert back the buyer to the site. It also did not award a commission to the Affiliate that referred the sale.

Please help someone...

Refer to this thread to see what I've done in regards to setting up PayPal Standard & IPN: http://www.cubecart.com/site/forums/index....indpost&p=92322

For the two tests that I just did, I did one as a paypal account holder and I did another as a non-paypal account holder and paid with a credit card. In both instances after the payment is successful, it reaches the main PayPal home page or logs me in to PayPal.

In my back office in CubeCart, it shows that the orders came through and it shows "Processing".

I know this is not in specific to just the PayPal IPN/Auto return topic, but can someone point me to the right direction in fixing the problems I am having where:

1. When paying through PayPal Standard & IPN through either an account holder or non-account holder of paypal that I do not get redirected back to the store when I should.

2. That the affiliate that referred the sale should be awarded with the commission. The affiliate module I am using is iDevAffiliate.

3. That the relevant emails from CubeCart is sent out (This is another problem I've encounted - earlier emails were working fine but now they are not).

I am using CC 3.0.9.

If someone has the solution for this or can spend sometime to help me fix these issues, I'll be even willing to pay for your services.

Thanks.

Share this post


Link to post
Share on other sites

Posted · Report post

Awesome job go77306 - your Paypal IPN fix worked like a charm. Thanks a million for figuring it out. I was just ready to restore a backup to a previous version when I stumbled across your fix. This was a problem incurred when upgrading to version 3.0.10

Share this post


Link to post
Share on other sites