paypal ipn not working, send to failed.php

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

jonnyfortis
Forum Contributor
Posts: 462
Joined: Tue Jan 10, 2012 6:05 am

paypal ipn not working, send to failed.php

Post by jonnyfortis »

Hello, i really hope someone can see where i am going wrong

i have the following pages set up.

checkout.php - this sends all the payment information to
paypal.php - this sends all the correct variables to paypal

this works.
i also have

notify.php - this is the page the the IPN is directed to.
return.php - this contains the if statement to either direct to success.php or failed-order.php
success.php - the contains the update stock in db commands.
cancel.php - this kills the session

payments are sent correctly, but on the return in always sends the user back to failed-order.php even when the order goes through therefore will not update my database.

i haven't included any code because i don't know what part to include because i have no idea where it is going wrong.

if someone can help and tell me what script to post that would be a start i hope

thanks in advace
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: paypal ipn not working, send to failed.php

Post by Christopher »

Which of those scripts are called via the URL and which are included by other scripts?
(#10850)
jonnyfortis
Forum Contributor
Posts: 462
Joined: Tue Jan 10, 2012 6:05 am

Re: paypal ipn not working, send to failed.php

Post by jonnyfortis »

ok thanks for replying
paypal.php is called by checkout.php
notify.php is the url that i have inserted into the IPN setting on the paypal website

within the paypal.php i have the following called

Code: Select all

$notifyvalue = "http://www.website.com/notify.php";
$returnvalue = "http://www.website.com/return.php";
$cancelvalue = "http://www.website.com/cancel.php";
return.php is also the return page on the paypal website settings
success.php is called in the if statement from return.php

Code: Select all

if ($row_rsReturn['fullfilled'] == 1) {
  header ("Location: success.php");
} else header ("Location: failed-order.php");
the same for failed-order.php


thanks in advance
Eric!
DevNet Resident
Posts: 1146
Joined: Sun Jun 14, 2009 3:13 pm

Re: paypal ipn not working, send to failed.php

Post by Eric! »

You should take a look at where $row_rsReturn['fullfilled'] gets defined. This isn't a IPN value, so I suspect the problem is with the code defining this value.
jonnyfortis
Forum Contributor
Posts: 462
Joined: Tue Jan 10, 2012 6:05 am

Re: paypal ipn not working, send to failed.php

Post by jonnyfortis »

On the notify page i have the following script that updates the order table

Code: Select all

// update orders table
if ($itemNumber != "" && $txnID != "" && $paymentStatus != "") {
  mysql_select_db($database_lachic, $lachic);
  $IPN_upd = "UPDATE lachic_Orders SET fulfilled = " . $status . ", transactID = '" . $txnID . "', paymentStatus = '" . $paymentStatus . "', errmsg = '" . $errmsg . "' WHERE OrderID = " . $itemNumber;
  $IPN_rsId = mysql_query($IPN_upd, $lachic) or die(mysql_error());
  $IPN_rsId = null;
}
then the if statement

Code: Select all

if ($row_rsReturn['fullfilled'] == 1) {
  header ("Location: success.php");
} else header ("Location: failed-order.php");
gets its value from this column on the database so would this need to be an IPN value

another thing i have changed the spelling of the fullfilled to the correct spelling of fulfilled.
Eric!
DevNet Resident
Posts: 1146
Joined: Sun Jun 14, 2009 3:13 pm

Re: paypal ipn not working, send to failed.php

Post by Eric! »

Where are you getting the value for "fullfulled"? Are you setting it somewhere? Are you expecting it to come from PayPal? Obviously at that point in your code is it NOT EQUAL to 1....

If $status represents the value from "payment_status" then it will never equal one. Payment_Status values are:
[text]The status of the payment:

Canceled_Reversal: A reversal has been canceled. For example, you won a dispute with the customer, and the funds for the transaction that was reversed have been returned to you.

Completed: The payment has been completed, and the funds have been added successfully to your account balance.

Created: A German ELV payment is made using Express Checkout.

Denied: You denied the payment. This happens only if the payment was previously pending because of possible reasons described for the pending_reason variable or the Fraud_Management_Filters_x variable.

Expired: This authorization has expired and cannot be captured.

Failed: The payment has failed. This happens only if the payment was made from your customer’s bank account.

Pending: The payment is pending. See pending_reason for more information.

Refunded: You refunded the payment.

Reversed: A payment was reversed due to a chargeback or other type of reversal. The funds have been removed from your account balance and returned to the buyer. The reason for the reversal is specified in the ReasonCode element.

Processed: A payment has been accepted.

Voided: This authorization has been voided.[/text]

"1" won't come from PayPal because it isn't a IPN value for payment_status: https://cms.paypal.com/us/cgi-bin/?cmd= ... TVariables
jonnyfortis
Forum Contributor
Posts: 462
Joined: Tue Jan 10, 2012 6:05 am

Re: paypal ipn not working, send to failed.php

Post by jonnyfortis »

Where are you getting the value for "fullfulled"?
this is the notify.php code that is the url from paypal ipn

Code: Select all

<?php
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
  $value = urlencode(stripslashes($value));
  $req .= "&$key=$value";
}
// 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.paypal.com', 80, $errno, $errstr, 30);
// assign posted variables to local variables
// note: additional IPN variables also available -- see IPN documentation
$itemNumber = $_POST['item_number'];
$paymentStatus = $_POST['payment_status'];
$payerStatus = $_POST['payer_status'];
$pendingReason = $_POST['pending_reason'];
$txnID = $_POST['txn_id'];
$receiverEmail = $_POST['receiver_email'];

mysql_select_db($database_lachic, $lachic); // find Txn ID
$query_rsTxnId = "SELECT transactID FROM lachic_Orders WHERE transactID = '" . $txnID . "'";
$rsTxnId = mysql_query($query_rsTxnId, $lachic) or die(mysql_error());
$row_rsTxnId = mysql_fetch_assoc($rsTxnId);
$totalRows_rsTxnId = mysql_num_rows($rsTxnId);

// Check notification validation
if (!$fp) {
  $errmsg = "$errstr ($errno)";
} else {
  fputs ($fp, $header . $req);
  while (!feof($fp)) {
    $res = fgets ($fp, 1024);
    if (strcmp ($res, "VERIFIED") == 0) {
      if ($paymentStatus != "Completed") {
        $errmsg = "Payment is " . $paymentStatus . " (" . $pendingReason . ")";
      } else
      if ($totalRows_rsTxnId > 0) {
        $errmsg = "This Txn ID has been used";
      } else
      if ($receiverEmail != "hello@email.com") {
        $errmsg = "The receiver email is incorrect";
      } else
      if ($payerStatus != "verified" && $payerStatus != "intl_verified") {
        $errmsg = "Your account is not Verified";
      } else
      {
        $errmsg = "";
      }
    }
    else if (strcmp ($res, "INVALID") == 0) {
      $errmsg = "Request is INVALID";
    }
  }
  fclose ($fp);
}
// last check
if ($errmsg != "") {
  $status = 0;
} else {
  $status = 1;
}

// update orders table
if ($itemNumber != "" && $txnID != "" && $paymentStatus != "") {
  mysql_select_db($database_lachic, $lachic);
  $IPN_upd = "UPDATE lachic_Orders SET fulfilled = " . $status . ", transactID = '" . $txnID . "', paymentStatus = '" . $paymentStatus . "', errmsg = '" . $errmsg . "' WHERE OrderID = " . $itemNumber;
  $IPN_rsId = mysql_query($IPN_upd, $lachic) or die(mysql_error());
  $IPN_rsId = null;
}
?>
is this what you mean?
Are you expecting it to come from PayPal?
like i say this is the update order information and this is where all the ipn information comes from.

looking at the fact that i am always getting redirected to failed and the purchase is going through i was thinking that it is just because the fulfilled value is not changing. So looking at that this page is where all the ipn information is collected.

i hope you can help me

thanks in advance
Eric!
DevNet Resident
Posts: 1146
Joined: Sun Jun 14, 2009 3:13 pm

Re: paypal ipn not working, send to failed.php

Post by Eric! »

That's not exactly what I meant, because you didn't post your code until now. Now I can see that $status is set to 1 or 0 and it is a product of payment_status and some error checking, rather than the IPN value of payment_status.

Looks like you have some logic debugging to do. Have you looked in your database to see what the results are? Is the fullfilled field set to 1 or 0? Does the database actually get updated? You have a lot of weird things going on with values being posted, but not verified (or filtered). Without access to the data in your variables it's hard to guess.

I do see this

Code: Select all

if (strcmp ($res, "VERIFIED") == 0)
and no sign of $res being set to anything. Also is the case correct for what your testing?

Do you have all the errors and notifications turned on while you are testing? You should be getting PHP notices with this code that would clue you in to potential problems.
jonnyfortis
Forum Contributor
Posts: 462
Joined: Tue Jan 10, 2012 6:05 am

Re: paypal ipn not working, send to failed.php

Post by jonnyfortis »

Have you looked in your database to see what the results are?
it looks like no values are being passed to the columns in the DB
Is the fullfilled field set to 1 or 0?
yes the value in the DB is set to 0 on tinyint(1)
Does the database actually get updated?
by the looks of it no.
You have a lot of weird things going on with values being posted, but not verified (or filtered). Without access to the data in your variables it's hard to guess.
shall i post the other pages?

thank so much for your help so far
jonnyfortis
Forum Contributor
Posts: 462
Joined: Tue Jan 10, 2012 6:05 am

Re: paypal ipn not working, send to failed.php

Post by jonnyfortis »

and no sign of $res being set to anything. Also is the case correct for what your testing?
this is at the top of the script

Code: Select all

$req .= "&$key=$value";
Do you have all the errors and notifications turned on while you are testing?
shall i add

Code: Select all

ini_set('display_errors',1); 
 error_reporting(E_ALL);
to the header script?
thanks
Eric!
DevNet Resident
Posts: 1146
Joined: Sun Jun 14, 2009 3:13 pm

Re: paypal ipn not working, send to failed.php

Post by Eric! »

jonnyfortis wrote:
and no sign of $res being set to anything. Also is the case correct for what your testing?
this is at the top of the script

Code: Select all

$req .= "&$key=$value";
Take a closer look. It's res (with an S) in your code, not req.

I suggest you put

Code: Select all

error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
to get the full effect. It would pick up the fact you are testing an undefined $res variable and give you a notice.
jonnyfortis
Forum Contributor
Posts: 462
Joined: Tue Jan 10, 2012 6:05 am

Re: paypal ipn not working, send to failed.php

Post by jonnyfortis »

Take a closer look. It's res (with an S) in your code, not req.
my mistake thats another variable
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
does this error reporting go on the top of each page?
jonnyfortis
Forum Contributor
Posts: 462
Joined: Tue Jan 10, 2012 6:05 am

Re: paypal ipn not working, send to failed.php

Post by jonnyfortis »

I really wish I hadn’t seen this as I really want one now!
whats this post?
jonnyfortis
Forum Contributor
Posts: 462
Joined: Tue Jan 10, 2012 6:05 am

Re: paypal ipn not working, send to failed.php

Post by jonnyfortis »

I added the error reporting to the notify page and made a payment via paypal but nothing happened it just directed staraight to payment failed, even though the payment went through

Code: Select all

<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
  $value = urlencode(stripslashes($value));
  $req .= "&$key=$value";
}
// 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.paypal.com', 80, $errno, $errstr, 30);
// assign posted variables to local variables
// note: additional IPN variables also available -- see IPN documentation
$itemNumber = $_POST['item_number'];
$paymentStatus = $_POST['payment_status'];
$payerStatus = $_POST['payer_status'];
$pendingReason = $_POST['pending_reason'];
$txnID = $_POST['txn_id'];
$receiverEmail = $_POST['receiver_email'];

mysql_select_db($database_lachic, $lachic); // find Txn ID
$query_rsTxnId = "SELECT transactID FROM lachic_Orders WHERE transactID = '" . $txnID . "'";
$rsTxnId = mysql_query($query_rsTxnId, $lachic) or die(mysql_error());
$row_rsTxnId = mysql_fetch_assoc($rsTxnId);
$totalRows_rsTxnId = mysql_num_rows($rsTxnId);

// Check notification validation
if (!$fp) {
  $errmsg = "$errstr ($errno)";
} else {
  fputs ($fp, $header . $req);
  while (!feof($fp)) {
    $res = fgets ($fp, 1024);
    if (strcmp ($res, "VERIFIED") == 0) {
      if ($paymentStatus != "Completed") {
        $errmsg = "Payment is " . $paymentStatus . " (" . $pendingReason . ")";
      } else
      {
        $errmsg = "";
      }
    }
    else if (strcmp ($res, "INVALID") == 0) {
      $errmsg = "Request is INVALID";
    }
  }
  fclose ($fp);
}
// last check
if ($errmsg != "") {
  $status = 0;
} else {
  $status = 1;
}

// update orders table
if ($itemNumber != "" && $txnID != "" && $paymentStatus != "") {
  mysql_select_db($database_lachic, $lachic);
  $IPN_upd = "UPDATE lachic_Orders SET fulfilled = " . $status . ", transactID = '" . $txnID . "', paymentStatus = '" . $paymentStatus . "', errmsg = '" . $errmsg . "' WHERE OrderID = " . $itemNumber;
  $IPN_rsId = mysql_query($IPN_upd, $lachic) or die(mysql_error());
  $IPN_rsId = null;
}
?>
jonnyfortis
Forum Contributor
Posts: 462
Joined: Tue Jan 10, 2012 6:05 am

Re: paypal ipn not working, send to failed.php

Post by jonnyfortis »

i thought it would be easier to post all the pages that might be the issue

paypal.php - this page sends data to paypal after the checkout.php

Code: Select all

<?php
// variables to send
if (!session_id()) session_start();
$business = "lachic@net.com";
$itemNumber = $_SESSION["orderID"];
$itemName = "Shopping at lachic";
$notifyvalue = "http://www.website.com/notify.php";
$returnvalue = "http://www.website.com/return.php";
$cancelvalue = "http://www.website.com/cancel.php";
$amount = $_GET["amount"];
$curr = "GBP";
$firstN = $_GET["firstname"];
$lastN = $_GET["lastname"];
$emailC = $_GET["cemail"];


$useSessions = true;
$XCName = "Cart";
$XCTimeout = 30;
$XC_ColNames=array("ProductID","Quantity","Name","Price","Total");
$XC_ComputedCols=array("","","","","Price");
require_once('XCInc/XCart.inc');
?>
then i have notify.php - this is the IPN address i insert in the paypal website

Code: Select all

<?php
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
  $value = urlencode(stripslashes($value));
  $req .= "&$key=$value";
}
// 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.paypal.com', 80, $errno, $errstr, 30);
// assign posted variables to local variables
// note: additional IPN variables also available -- see IPN documentation
$itemNumber = $_POST['item_number'];
$paymentStatus = $_POST['payment_status'];
$payerStatus = $_POST['payer_status'];
$pendingReason = $_POST['pending_reason'];
$txnID = $_POST['txn_id'];
$receiverEmail = $_POST['receiver_email'];

mysql_select_db($database_lachic, $lachic); // find Txn ID
$query_rsTxnId = "SELECT transactID FROM lachic_Orders WHERE transactID = '" . $txnID . "'";
$rsTxnId = mysql_query($query_rsTxnId, $lachic) or die(mysql_error());
$row_rsTxnId = mysql_fetch_assoc($rsTxnId);
$totalRows_rsTxnId = mysql_num_rows($rsTxnId);

// Check notification validation
if (!$fp) {
  $errmsg = "$errstr ($errno)";
} else {
  fputs ($fp, $header . $req);
  while (!feof($fp)) {
    $res = fgets ($fp, 1024);
    if (strcmp ($res, "VERIFIED") == 0) {
      if ($paymentStatus != "Completed") {
        $errmsg = "Payment is " . $paymentStatus . " (" . $pendingReason . ")";
      } else
      {
        $errmsg = "";
      }
    }
    else if (strcmp ($res, "INVALID") == 0) {
      $errmsg = "Request is INVALID";
    }
  }
  fclose ($fp);
}
// last check
if ($errmsg != "") {
  $status = 0;
} else {
  $status = 1;
}

// update orders table
if ($itemNumber != "" && $txnID != "" && $paymentStatus != "") {
  mysql_select_db($database_lachic, $lachic);
  $IPN_upd = "UPDATE lachic_Orders SET fulfilled = " . $status . ", transactID = '" . $txnID . "', paymentStatus = '" . $paymentStatus . "', errmsg = '" . $errmsg . "' WHERE OrderID = " . $itemNumber;
  $IPN_rsId = mysql_query($IPN_upd, $lachic) or die(mysql_error());
  $IPN_rsId = null;
}
?>
then i have the return.php - this is the return address inserted in the paypal website

Code: Select all

<?php
if (!function_exists("GetSQLValueString")) {
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") 
{
  if (PHP_VERSION < 6) {
    $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;
  }

  $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

  switch ($theType) {
    case "text":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;    
    case "long":
    case "int":
      $theValue = ($theValue != "") ? intval($theValue) : "NULL";
      break;
    case "double":
      $theValue = ($theValue != "") ? doubleval($theValue) : "NULL";
      break;
    case "date":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;
    case "defined":
      $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
      break;
  }
  return $theValue;
}
}

mysql_select_db($database_lachic, $lachic);
$query_rsReturn = "SELECT * FROM lachic_Orders";
$rsReturn = mysql_query($query_rsReturn, $lachic) or die(mysql_error());
$row_rsReturn = mysql_fetch_assoc($rsReturn);
$totalRows_rsReturn = mysql_num_rows($rsReturn);

if ($row_rsReturn['fulfilled'] == 1) {
  header ("Location: success.php");
} else header ("Location: failed-order.php");
?>
then this is the success.php ehich updates the stock in the DB

Code: Select all

<?php
// *** Update the stock *** 
$details_table = "lachic_OrdersDetails";
$ID_column = "ID";
$details_prodID = "ProductID";
$details_qty = "Quantity";
$XStock_TableName = "lachic_prod";
$XStock_FieldName = "stock";
$XStock_unID = "prodID";
if (!session_id()) session_start();
if (isset($_SESSION["orderID"])) {
  mysql_select_db($database_lachic, $lachic);
  $details_Source = "select * from " .  $details_table . " where " . $ID_column . " = " . $_SESSION["orderID"];
  $detailsRS = mysql_query($details_Source, $lachic) or die(mysql_error());
  $row_detailsRS = mysql_fetch_assoc($detailsRS);
  do {
    $XStock_qtySource = "select " . $XStock_FieldName . " from " .  $XStock_TableName . " where " . $XStock_unID . " = " . $row_detailsRS[$details_prodID] . "";
    $XStock_rsUpd = mysql_query($XStock_qtySource, $lachic) or die(mysql_error());
    $row_XStock_rsUpd = mysql_fetch_assoc($XStock_rsUpd);
    if ($row_XStock_rsUpd[$XStock_FieldName] > 0) {
      $XStock_new = $row_XStock_rsUpd[$XStock_FieldName] - $row_detailsRS[$details_qty];
      if ($XStock_new < 0) $XStock_new = 0;
      $XStock_UpdSource = "update " . $XStock_TableName . " set " . $XStock_FieldName . " = " . $XStock_new . " where " . $XStock_unID . " = " . $row_detailsRS[$details_prodID] . "";
      $XStock_rsUpd = mysql_query($XStock_UpdSource, $lachic) or die(mysql_error());
    }
  } while ($row_detailsRS = mysql_fetch_assoc($detailsRS));
  $XStock_rsUpd = null;
  $detailsRS = null;
  session_unregister("orderID");
}
?>
so the full process is shoppingcart.php - paypal.php - paypal site - notify.php - return.php then either success.php or failed.php

thanks
Last edited by jonnyfortis on Fri Dec 21, 2012 10:32 am, edited 1 time in total.
Post Reply