CodingForums.com

CodingForums.com (http://www.codingforums.com/index.php)
-   PHP (http://www.codingforums.com/forumdisplay.php?f=6)
-   -   Paypal IPN listener help (http://www.codingforums.com/showthread.php?t=279949)

toddbuckles 10-29-2012 12:01 AM

Paypal IPN listener help
 
I think I have tried everything, but obviously not. I have the issue narrowed to the fsocketopen part. When I use the ssl:// address in the tutorials, i get 400 bad request returned. when I use www.sandbox.paypal.com, 80... It returns

Quote:

POST /cgi-bin/webscr HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 837

cmd=_notify-validate&test_ipn=1&payment_type=instant&payment_date=10%3A32%3A00+Oct+28%2C+2012+PDT&payment_status =Completed&address_status=confirmed&paye...
Never returns "verified", although verified is passed in the original $_POST data under payer_status.

Code never makes it past if (strcmp ($res, "VERIFIED") == 0) {

Here is the code I am using...

PHP Code:

<?PHP
require '../glob.inc.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.sandbox.paypal.com'80$errno$errstr30);


// assign posted variables to local variables
$item_name $_POST['item_name'];
$item_number $_POST['item_number'];
$payment_status $_POST['payment_status'];
$payment_amount $_POST['mc_gross'];
$payment_currency $_POST['mc_currency'];
$txn_id $_POST['txn_id'];
$receiver_email $_POST['receiver_email'];
$payer_email $_POST['payer_email'];
$memnum mysql_real_escape_string($_POST['custom']);  //our users ID


if (!$fp) {
   
// HTTP ERROR
} else {
  
fputs ($fp$header.$req);
  while (!
feof($fp)) {
    
$res fgets ($fp1024);
    
 
//the two lines below are only so I can see what is going on by logging to my database.  I am not sure how to create an error log file.
    
$payer_email $res;    
    
$log_query mysql_query("INSERT INTO ipn_log VALUES ('','".$memnum."','".$txn_id."','".$payer_email."','".$header.$req."')");
    
    if (
strcmp ($res"VERIFIED") == 0) {
    
    
//code never makes it to this point.
    
        
if ($payment_status=='Completed'){
            
$txn_id_check mysql_query("SELECT 'txn_id' FROM 'log' WHERE 'txn_id'='".$txn_id."'");
            if (
mysql_num_rows($txn_id_check)!=1){
                
                if (
$receiver_email == 'myemailaddress'){
                    
                    
//if ($payment_amount == '20.00' && $payment_currency == 'USD') {
                        //add txn_id to database log table
                        
$log_query mysql_query("INSERT INTO ipn_log VALUES ('','".$memnum."','".$txn_id."','".$payer_email."')");
                        
//update paid field
                        
$update_paid mysql_query("UPDATE members SET cknum='".$txn_id."', Amount='".$payment_amount." WHERE 'memid'='".$memnum."'");
                    
//}
                
                
}
            }    
        }
    }
    else if (
strcmp ($res"INVALID") == 0) {
         
// log for manual investigation
    
}
  }
  
fclose ($fp);
}
?>

Any help you can give would certainly be appreciated.

Thanks in advance,

TB

toddbuckles 11-09-2012 02:11 PM

Just in case someone stumbles on this and has the same problem, I was unable to resolve it. Instead, I went the cURL route, and it worked beautifully. I am not sure why the difference, but it solved the problem. Since I had no experience with cURL, it was a learning curve for me, but I made it through.

Here is my code that worked: I connect through a glob.inc.php, search that for more info.

PHP Code:


// STEP 1: Read POST data

// reading posted data directly from $_POST causes serialization issues with array data in POST
// read raw POST data from input stream instead. 
$raw_post_data file_get_contents('php://input'); //read-only stream that allows you to read raw data from the request body.  Result is a string...
$raw_post_array explode('&'$raw_post_data);  //put the string into an array
$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.paypal.com/cgi-bin/webscr');  //initialize the curl session, and store it in object $ch

//below are the options applied to $ch
curl_setopt($chCURLOPT_HTTP_VERSIONCURL_HTTP_VERSION_1_1); //pretty obvious, sets http version.  paypal requires 1.1

curl_setopt($chCURLOPT_POST1);  //tells curl to do a regular post (the 1 option indicates 'true'

curl_setopt($chCURLOPT_RETURNTRANSFER,1);  //maybe someone can explain, manual states 'TRUE to return the transfer as a string of the return value of curl_exec() instead of outputting it out directly.'

curl_setopt($chCURLOPT_POSTFIELDS$req); //finally, the data we are posting.  Parsed above in the foreach statements

curl_setopt($chCURLOPT_SSL_VERIFYPEER1); //set to true here to verify paypal certificate

curl_setopt($chCURLOPT_SSL_VERIFYHOST2);  //could use help here.  paypal states 1 to check the existence of a common name in the SSL peer certificate. 2 to check the existence of a common name and also verify that it matches the hostname provided. In production environments the value of this option should be kept at 2 (default value).

curl_setopt($chCURLOPT_FORBID_REUSE1); //closes the connection as soon as it is finished processing without pooling data

curl_setopt($chCURLOPT_HTTPHEADER, array('Connection: Close')); //adds connection close to header

// 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)) ) {  //and, we execute the cURL with all options set as above and log an error if it comes back empty.  Should return 'VERIFIED'
    // 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) {

     
// assign posted variables to local variables
    
$item_name $_POST['item_name'];
    
$item_number $_POST['item_number'];
    
$payment_status $_POST['payment_status'];
    
$payment_amount $_POST['mc_gross'];
    
$payment_currency $_POST['mc_currency'];
    
$txn_id $_POST['txn_id'];
    
$receiver_email $_POST['receiver_email'];
    
$payer_email $_POST['payer_email'];
    
$payment_date date('Y-m-d'strtotime($_POST['payment_date']));
    
$memid mysql_real_escape_string($_POST['custom']);  //our users ID
    
    // check whether the payment_status is Completed
    
if ($payment_status=='Completed'){
        
// check that txn_id has not been previously processed
        
$txn_id_check mysql_query("SELECT 'cknum' FROM 'members' WHERE 'cknum'='".$txn_id."'"); //cknum is a field specific to my db.
        
if (mysql_num_rows($txn_id_check)!=1){  //we don't already have that txn_id stored
            // check that receiver_email is your Primary PayPal email
            
if ($receiver_email == 'yourpaypalemail@here.com'){
                
// check that payment_amount/payment_currency are correct
                
if ($payment_amount == 'your amount' && $payment_currency == 'USD') {
                    
// process payment
                    //add values to database members table
                    
$log_query mysql_query("UPDATE members SET receipt='Yes', Amount='$payment_amount', paytype='Paypal', cknum='$txn_id', paid_thru='$payment_date' WHERE memid='$memid'");    //or whatever our sql statement is, or an email string, or whatever you want to execute.                
                
}
            }
        }    
    }
} else if (
strcmp ($res"INVALID") == 0) {
    
// log for manual investigation
    
$memid mysql_real_escape_string($_POST['custom']);  //our users ID
    
$log_query mysql_query("UPDATE members SET receipt='No', cknum='INVALID' WHERE memid='$memid'");
}
?> 

I really hope this helps someone.

TB

Fumigator 11-09-2012 11:40 PM

Thanks for posting the solution you ended up using. I'm not sure why using fsockopen() wouldn't work for you-- nothing jumped out at me. It's what I use and I have no problems with it.

minder 11-09-2012 11:57 PM

Quote:

Originally Posted by Fumigator (Post 1290516)
Thanks for posting the solution you ended up using. I'm not sure why using fsockopen() wouldn't work for you-- nothing jumped out at me. It's what I use and I have no problems with it.

[ot]

My ISP has fsockopen disabled by default on its hosting accounts citing security reasons.

After I submitted a support ticket explaining why I needed it enabled on my hosting account (all legitimate reasons), they enabled it on my account. Perhaps the op's hosting account also has fsockopen disabled.

[/ot]

felgall 11-10-2012 12:59 AM

A lot of web hosts only have fsocketopen enabled for specific ports - although 80 is probably the one that they are most likely to have open if they allow it on any. The hosts I have used have only ever allowed it on shared hosting on ports 80 and 443.

In my experience cURL is more likely to be disabled on the hosting which is presumably why Paypal used fsocketopen instead in their example code.


All times are GMT +1. The time now is 06:43 PM.

Powered by vBulletin®
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.