Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 5 of 5
  1. #1
    New to the CF scene
    Join Date
    Apr 2011
    Posts
    6
    Thanks
    0
    Thanked 0 Times in 0 Posts

    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

    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

  • #2
    New to the CF scene
    Join Date
    Apr 2011
    Posts
    6
    Thanks
    0
    Thanked 0 Times in 0 Posts
    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

  • #3
    UE Antagonizer Fumigator's Avatar
    Join Date
    Dec 2005
    Location
    Utah, USA, Northwestern hemisphere, Earth, Solar System, Milky Way Galaxy, Alpha Quadrant
    Posts
    7,691
    Thanks
    42
    Thanked 637 Times in 625 Posts
    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.

  • #4
    Banned
    Join Date
    Oct 2012
    Posts
    81
    Thanks
    0
    Thanked 4 Times in 4 Posts
    Quote Originally Posted by Fumigator View Post
    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]

  • #5
    Master Coder felgall's Avatar
    Join Date
    Sep 2005
    Location
    Sydney, Australia
    Posts
    6,462
    Thanks
    0
    Thanked 633 Times in 623 Posts
    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.
    Stephen
    Learn Modern JavaScript - http://javascriptexample.net/
    Helping others to solve their computer problem at http://www.felgall.com/

    Don't forget to start your JavaScript code with "use strict"; which makes it easier to find errors in your code.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •