2

i am using the following code for my paypal configuration here's the code

///Paypal Array///
                            $data=array(
                            //merchant email for live
                            //'merchant_email'=>'sumofish@yahoo.com',
                            //merchant email for test
                            'merchant_email'=>'uneebmir321-facilitator@yahoo.com',
                            'product_name'=>$bundleplan." Bundle Plan",
                            's_amount'=>$bundle_came_price,     // Second` Amount
                            's_cycle'=>'M',         //Second Period M=montrh,Y=year ,D=Days, W='week'
                            's_period'=>$period,    // Second Cycle
                            //see small_price fucntionality again
                            'small_price'=>$bundle_came_price,
                            ////see small_price fucntionality again
                            'currency_code'=>'USD',
                            'thanks_page'=>"https://".$_SERVER['HTTP_HOST'].'/puppy/puppy/thanks222.php',
                            'notify_url'=>"https://puppybundle.com/beta/ipn.php",
                            'cancel_url'=>"https://puppybundle.com/beta/index.php",
                            //true for sandbox false for live
                            'paypal_mode'=>true,
                            //true for sandbox false for live
                            'currency_symbole'=>'$'
                            );
                ///Paypal Array///

and here's the ipn class

<?php
session_start();
$unique_id=$_SESSION['unique_id'];
include("db.php");
file_put_contents("newfile.txt",var_export($_POST,true));
$status="not_completed";
                            $status2="paid";
                            $status3="remaining";
                            $zero=0;
                            $currency="CAD";
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$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.sandbox.paypal.com/cgi-bin/webscr'); // change to [...]sandbox.paypal[...] when using sandbox to test
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));

// 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)) ) {
    // 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 (trim($res), "VERIFIED") == 0) {
    // check whether the payment_status is Completed
    // check that txn_id has not been previously processed
    // check that receiver_email is your Primary PayPal email
    // check that payment_amount/payment_currency are correct
    // process payment

    // assign posted variables to local variables


     $price = $_POST['mc_gross'];
     $currency = $_POST['mc_currency'];
     $payer_email = $_POST['payer_email'];
     $txn_id=$_POST['txn_id'];

    $item_name = $_POST['item_name'];
        if($item_name=="Small Bundle Plan"){

            $item_name="small";
        }

parse_str($_POST['custom'],$_MYVAR);

$custom =$_MYVAR['id'];
$unique_id =$_MYVAR['unique_id'];
trim($custom);
$txt =$custom;
    $currency_code= $_POST['currency_code'];
    $fulldate = gmdate('Y-m-d H:i:s');
    if($txn_id){

    $query="UPDATE `puppy_pending_transaction` SET `status`=? WHERE unique_id=?";
                            $stmt = $db->prepare($query);
                            if($stmt){
                                $stmt->bind_param("ss", $status2,$unique_id);
                                $stmt->execute();   
                                $stmt->close();         
                            } 


$query="INSERT INTO `puppy_transaction_confirmed`(`transaction_id`,`unique_id`, `user_id`, `payer_email`, `transaction_time`, `package`, `amount`, `currency`,`status_delivery`) VALUES (?,?,?,?,?,?,?,?,?)";
                            $stmt = $db->prepare($query);

                            if($stmt) 
                            {
                                $check=$stmt->bind_param("sssssssss",$txn_id,$unique_id,$custom,$payer_email,$fulldate,$item_name,$price,$currency,$status);
                                $stmt->execute();               
                                $stmt->close();
                            }

$query="INSERT INTO `puppy_paid_transaction_record`(`unique_id`, `month_delivered`, `total`,`status`) VALUES (?,?,?,?)";
                            $stmt = $db->prepare($query);
                            if($stmt){
                                $stmt->bind_param("ssss", $unique_id,$zero,$item_name,$status3);
                                $stmt->execute();   
                                $stmt->close();         
                            } 
    }   
} else if (strcmp ($res, "INVALID") == 0) {
    // log for manual investigation 
}
?>

the problem is this code is working 100% fine for sandbox now what i did for live version is to change the merchant email to client email and paypal_mode to false for live testing and one other thing i changed the

`$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');

in the ipn class to

`$ch = curl_init('https://www.paypal.com/cgi-bin/webscr');`

for live mode i have used ipn simulator to validate my file and it is ok more over i am sure about the ipn path i set in paypal for merchant that is also ok am sure of it, i dont know whats wrong! can anybody point me on the right direction?

uneeb
  • 69
  • 1
  • 10
  • Paypal have finally got round to using classes and building a (vaguely) proper payment IPN class, [you can use it here](https://github.com/paypal/ipn-code-samples/tree/master/php) . Download it and particulary use the new `.pem` file as it correctly contains their server security certificate which had caused endless secondary issues, up to this point. – Martin Nov 11 '16 at 12:09
  • thats great! but where do i do my custom coding – uneeb Nov 11 '16 at 12:58
  • well open their PHP file and copy their newer code over their code you have on your page and update details as needed. – Martin Nov 11 '16 at 13:03
  • alright i am giving it a go – uneeb Nov 11 '16 at 13:04
  • i am getting this error! Uncaught exception 'Exception' with message 'PayPal responded with http code 0' in /home/mike7860/public_html/puppybundle.com/beta/PaypalIPN.php:98 – uneeb Nov 11 '16 at 13:09
  • yeah you need to provide exception catching code, Paypal Doesn't do this unfortunately. I'm getting the impression that you're not too familiar with Object Orientated and/or rty/catch programming in PHP? – Martin Nov 11 '16 at 13:16
  • yea not very much i did most of my work using procedural php! will be shifting to Object Oriented in near future but in the mean time i need to get this done – uneeb Nov 11 '16 at 13:19
  • Ok 'm writing you an answer – Martin Nov 11 '16 at 13:20
  • much appreciated! thanks ...:) – uneeb Nov 11 '16 at 13:20
  • one more thing i just noticed your very first comment about the pem file i have'nt done anything to that yet how do i use that file – uneeb Nov 11 '16 at 13:24
  • Download the pem file from the github link and then save it somewhere on your sever, you will need to reference it from within cURL as outlined at the bottom of my answer. – Martin Nov 11 '16 at 13:28
  • As another concept, if you're developing a new website, I would also offer up [using Stripe](https://stripe.com/gb) to work with, it's easy to code, friendly to develop and misses out on all of this pissing about that Paypal always seems to inflict. Stripe is what Paypal Should be. – Martin Nov 11 '16 at 14:13

1 Answers1

1

As per downloading the newer PHP IPN code from here. You save the IPN class file to whereever you need it (exampled below in the same folder as your IPN file.

You will also need to setup a Exception catching routine as Paypal don't implement one by default (that's what the try{ ...} catch{} block does).

<?php
define("LOG_FILE", "paypal_ipn.log");
////edit
error_log("Log File Started:\n",3,LOG_FILE);

require('PaypalIPN.php'); //check path is correct. 
$ipn = new PayPalIPN();    
try {
    // Use the sandbox endpoint during testing.
    $ipn->useSandbox(); //comment this line out to use live version.
    $verified = $ipn->verifyIPN(); //returns true or false. 
    if ($verified) {
        /*****
         * Process IPN
         * A list of variables is available here:
         * https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNandPDTVariables/
         *
         * Here is where you add your data from your current setup, your own custom data to take the values from Paypal and process them.
         ****/
        // check whether the payment_status is Completed
        // check that txn_id has not been previously processed
        // check that receiver_email is your Primary PayPal email
        // check that payment_amount/payment_currency are correct
        // process payment

        // assign posted variables to local variables


        $price       = $_POST['mc_gross'];
        $currency    = $_POST['mc_currency'];
        $payer_email = $_POST['payer_email'];
        $txn_id      = $_POST['txn_id'];

        $item_name = $_POST['item_name'];
        if ($item_name == "Small Bundle Plan") {

            $item_name = "small";
        }

        parse_str($_POST['custom'], $_MYVAR);

        $custom    = $_MYVAR['id'];
        $unique_id = $_MYVAR['unique_id'];
        trim($custom);
        $txt           = $custom;
        $currency_code = $_POST['currency_code'];
        $fulldate      = gmdate('Y-m-d H:i:s');
        if ($txn_id) {

            $query = "UPDATE `puppy_pending_transaction` SET `status`=? WHERE unique_id=?";
            $stmt  = $db->prepare($query);
            if ($stmt) {
                $stmt->bind_param("ss", $status2, $unique_id);
                $stmt->execute();
                $stmt->close();
            }


            $query = "INSERT INTO `puppy_transaction_confirmed`(`transaction_id`,`unique_id`, `user_id`, `payer_email`, `transaction_time`, `package`, `amount`, `currency`,`status_delivery`) VALUES (?,?,?,?,?,?,?,?,?)";
            $stmt  = $db->prepare($query);

            if ($stmt) {
                $check = $stmt->bind_param("sssssssss", $txn_id, $unique_id, $custom, $payer_email, $fulldate, $item_name, $price, $currency, $status);
                $stmt->execute();
                $stmt->close();
            }

            $query = "INSERT INTO `puppy_paid_transaction_record`(`unique_id`, `month_delivered`, `total`,`status`) VALUES (?,?,?,?)";
            $stmt  = $db->prepare($query);
            if ($stmt) {
                $stmt->bind_param("ssss", $unique_id, $zero, $item_name, $status3);
                $stmt->execute();
                $stmt->close();
            }

            /***
             * End OP code
             ***/
        }
        // Reply with an empty 200 response to indicate to paypal the IPN was received correctly.
        header("HTTP/1.1 200 OK");
    }

}
catch (Exception $e) {
    error_log("There was a problem: ".$e->getMessage(),3,LOG_FILE);
}

I also highly recommend you download the associated .pem file and upload it to your server and adjust the reference to it on line 106 of the IPN class file. This pem file has a key for your server to communicate with the Paypal secure server and solves a large batch of historic problems relating to this.

You may need to tweak some of your own code for editing the incoming data but this script works for me much better than the older procedural Paypal code did.


.pem file clarification:

I may be easiest for at least testing perspective to simply have the Paypal Pem file in the same folder as you keep your paypal IPN class.

so line 106 of the class:

    if ($this->use_local_certs) {
        curl_setopt($ch, CURLOPT_CAINFO, "cacert.pem");
    }

and ensure that $this->use_local_certs = true;.

Martin
  • 19,815
  • 6
  • 53
  • 104
  • i really appreciate your concern towards my issue Martin but we are still there actually it is still not coming inside this condition if ($verified) and the update is that i am not getting any error as i was before – uneeb Nov 11 '16 at 13:52
  • any PHP errors? any error log errors? Did you tell Paypal in the account section the URL of the IPN? did you add the `.pem` file? – Martin Nov 11 '16 at 13:58
  • 1
    yup added the pem file ipn is fine and no php errors – uneeb Nov 11 '16 at 14:01
  • btw my cert file path is 'root/cert/cacert.pem' and in my PaypalIPN file the path i defined as curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . "/cert/cacert.pem"); is that correct? – uneeb Nov 11 '16 at 14:02
  • It's probably easiest to just put the pem file in the same directory as your PHP file, I doubt your cURL will have access to your root folder. – Martin Nov 11 '16 at 14:05
  • actually there is one issue i am using this line file_put_contents("newfile.txt","here"); just to confirm that it is comming inside my ipn.php file when i use my old code it is generating this file and rest is working fine but when i use your code it is not generating this file which means it is for some reason not comming inside ipn.php – uneeb Nov 11 '16 at 14:18
  • did you set up the log file as per my code? (`LOG_FILE`) it should report error to the error log file in your PHP directory (probably same directory as the files). BEcause the file is caled by a server rather than a browser you can't output the errors to screen so `error_log` is your friend here. be careful the `require` is case sensitive and will cease the script if it can't find the file. – Martin Nov 11 '16 at 14:28
  • @uneeb I'm really just picking at likely pitfalls, there's no data as to give us any clues as to why the IPN page is failing, the code above works on my production servers so I think the issue is user generated somewhere (sorry). So it's case sensitivity, or file referencing or Paypal account URL referencing to the IPN file, one of those three are the most likely causes. – Martin Nov 11 '16 at 14:29
  • the log file define("LOG_FILE", "paypal_ipn.log"); is not generated – uneeb Nov 11 '16 at 14:32
  • well thankyou so much for your help martin i will see to recomended issues u said thumbsup (y) keep up the good work – uneeb Nov 11 '16 at 14:34
  • ok it sounds increasingly like paypal is not calling the script, so can you double check that the paypal account URL for the IPN listener is correct, and that the url in the posted payment form is also correct, and I have also added a little "hello" to my script so regardless of any errors, the log file should produce something. if the script is called. – Martin Nov 11 '16 at 14:35
  • now i am sure the script is not been called because nothing is happening not yours not mine i am only confused that when i use my old code that is working which means that there is no issue from paypal url side but the file name is the same why not come to updated code file – uneeb Nov 11 '16 at 14:40
  • ok - progress! Right, so there are two places in Paypal to setup IPN listeners, somewhere in the accounts area (in some titty submenu; `Profile >> Profile and setting >> selling preferences >> website IPN` ) and in the URL given by the submitting form. It may be better to change the name of the IPN listener file to something different and then update the urls. I would also increasingly recommend exploring [Stripe](https://stripe.com/gb) `:-D` – Martin Nov 11 '16 at 14:44
  • haha yea but for now i have to stick with paypal, i was actually expecting paypal pro to give me issues it ran on the very first attempt but this became a headache for me – uneeb Nov 11 '16 at 14:49
  • actually i changed my approach i tried to access the file ipn.php directly and added a echo on top and guess what nothing happened which means what you were saying is true that somewhere it is getting stuck and when i comment your code from try to till the end it is showing the echo which means somewhere inside the code is a syntax issue can you look through your code again? – uneeb Nov 11 '16 at 15:17
  • add [PHP Error logging](http://stackoverflow.com/questions/3531703/how-to-log-errors-and-warnings-into-a-file) into your project and rerun the page and the error log will tell you what's wrong. – Martin Nov 11 '16 at 15:26
  • @uneeb an alternative (but *not* recommended) solution is to revert to your original code as in your question and set `CURLOPT_SSL_VERIFYPEER => FALSE,` – Martin Nov 11 '16 at 15:32
  • i think i will be moving along with your code and forget about the previous – uneeb Nov 11 '16 at 15:55
  • martin one more thing i reused the old code the main thing is paypal data is not comming in the ipn file i have verified from ipn listenener url settings that seems to be fine i used file_put_contents("newfile2.txt",var_export($_POST,true)); to verify it! ay suggestions? – uneeb Nov 11 '16 at 18:10