简体   繁体   中英

PayPal IPN for subscription - Works partially

I am running PayPal Subscription and I am trying to fire database writes based upon the response received. Up until yesterday, the code was working correctly. But today, strangely, the code stopped firing emails upon receiving payments. I am not sure if this is a glitch on PayPal's side or mine. I don't think its an issue with my code because I stripped a lot of code from it and I am currently using the basic version of IPN for payments tracking, but even then it does not make database inserts or fires emails.

I also searched SO for possible solutions & even implemented the ones that I found were close to my answer. But unfortunately, they didn't work. So here's my IPN code:

<?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";

// If testing on Sandbox use:
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);


// assign posted variables to local variables
$item_name = $_POST['item_name'];
$business = $_POST['business'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$mc_gross = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$receiver_id = $_POST['receiver_id'];
$quantity = $_POST['quantity'];
$num_cart_items = $_POST['num_cart_items'];
$payment_date = $_POST['payment_date'];
$first_name = $_POST['first_name'];
$last_name = $_POST['last_name'];
$payment_type = $_POST['payment_type'];
$payment_status = $_POST['payment_status'];
$payment_gross = $_POST['payment_gross'];
$payment_fee = $_POST['payment_fee'];
$settle_amount = $_POST['settle_amount'];
$memo = $_POST['memo'];
$payer_email = $_POST['payer_email'];
$txn_type = $_POST['txn_type'];
$payer_status = $_POST['payer_status'];
$address_street = $_POST['address_street'];
$address_city = $_POST['address_city'];
$address_state = $_POST['address_state'];
$address_zip = $_POST['address_zip'];
$address_country = $_POST['address_country'];
$address_status = $_POST['address_status'];
$item_number = $_POST['item_number'];
$tax = $_POST['tax'];
$option_name1 = $_POST['option_name1'];
$option_selection1 = $_POST['option_selection1'];
$option_name2 = $_POST['option_name2'];
$option_selection2 = $_POST['option_selection2'];
$for_auction = $_POST['for_auction'];
$invoice = $_POST['invoice'];
$custom = $_POST['custom'];
$notify_version = $_POST['notify_version'];
$verify_sign = $_POST['verify_sign'];
$payer_business_name = $_POST['payer_business_name'];
$payer_id =$_POST['payer_id'];
$mc_currency = $_POST['mc_currency'];
$mc_fee = $_POST['mc_fee'];
$exchange_rate = $_POST['exchange_rate'];
$settle_currency  = $_POST['settle_currency'];
$parent_txn_id  = $_POST['parent_txn_id'];
$pending_reason = $_POST['pending_reason'];
$reason_code = $_POST['reason_code'];


// subscription specific vars

$subscr_id = $_POST['subscr_id'];
$subscr_date = $_POST['subscr_date'];
$subscr_effective  = $_POST['subscr_effective'];
$period1 = $_POST['period1'];
$period2 = $_POST['period2'];
$period3 = $_POST['period3'];
$amount1 = $_POST['amount1'];
$amount2 = $_POST['amount2'];
$amount3 = $_POST['amount3'];
$mc_amount1 = $_POST['mc_amount1'];
$mc_amount2 = $_POST['mc_amount2'];
$mc_amount3 = $_POST['mcamount3'];
$recurring = $_POST['recurring'];
$reattempt = $_POST['reattempt'];
$retry_at = $_POST['retry_at'];
$recur_times = $_POST['recur_times'];
$username = $_POST['username'];
$password = $_POST['password'];

//auction specific vars

$for_auction = $_POST['for_auction'];
$auction_closing_date  = $_POST['auction_closing_date'];
$auction_multi_item  = $_POST['auction_multi_item'];
$auction_buyer_id  = $_POST['auction_buyer_id'];



$notify_email =  "myemail@domain.com"; //email address to which debug emails are sent to
$DB_Server = "host"; //your MySQL Server
$DB_Username = "user"; //your MySQL User Name
$DB_Password = "password"; //your MySQL Password
$DB_DBName = "dbname"; //your MySQL Database Name


if (!$fp) 
{
    // HTTP ERROR
} 
else 
{

    mail($notify_email, "IPN Triggered 1", "IPN Triggered 1");  

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

    while (!feof($fp)) 
    {
        //Already used this
        //$res = fgets ($fp, 1024);

        //Using this to see if it sends response
        $res = stream_get_contents($fp, 1024);


        if (strcmp ($res, "VERIFIED") == 0) 
        {   
            mail($notify_email, "VERIFIED 1", "VERIFIED 1");

            //create MySQL connection
            $Connect = mysql_connect($DB_Server, $DB_Username, $DB_Password)
            or die("Couldn't connect to MySQL:<br>" . mysql_error() . "<br>" . mysql_errno());


            //select database
            $Db = @mysql_select_db($DB_DBName, $Connect)
            or die("Couldn't select database:<br>" . mysql_error(). "<br>" . mysql_errno());


            $fecha = date("m")."/".date("d")."/".date("Y");
            $fecha = date("Y").date("m").date("d");

            //check if transaction ID has been processed before
            $checkquery = "select txnid from paypal_payment_info where txnid='".$txn_id."'";
            $sihay = mysql_query($checkquery) or die("Duplicate txn id check query failed:<br>" . mysql_error() . "<br>" . mysql_errno());
            $nm = mysql_num_rows($sihay);

            if ($nm == 0)
            {
                //execute query
                if ($txn_type == "cart")
                {
                    $strQuery = "insert into paypal_payment_info(paymentstatus,buyer_email,firstname,lastname,street,city,state,zipcode,country,mc_gross,mc_fee,memo,paymenttype,paymentdate,txnid,pendingreason,reasoncode,tax,datecreation) values ('".$payment_status."','".$payer_email."','".$first_name."','".$last_name."','".$address_street."','".$address_city."','".$address_state."','".$address_zip."','".$address_country."','".$mc_gross."','".$mc_fee."','".$memo."','".$payment_type."','".$payment_date."','".$txn_id."','".$pending_reason."','".$reason_code."','".$tax."','".$fecha."')";

                     $result = mysql_query($strQuery) or die("Cart - paypal_payment_info, Query failed:<br>" . mysql_error() . "<br>" . mysql_errno());

                     for ($i = 1; $i <= $num_cart_items; $i++) 
                     {
                         $itemname = "item_name".$i;
                         $itemnumber = "item_number".$i;
                         $on0 = "option_name1_".$i;
                         $os0 = "option_selection1_".$i;
                         $on1 = "option_name2_".$i;
                         $os1 = "option_selection2_".$i;
                         $quantity = "quantity".$i;

                         $struery = "insert into paypal_cart_info(txnid,itemnumber,itemname,os0,on0,os1,on1,quantity,invoice,custom) values ('".$txn_id."','".$_POST[$itemnumber]."','".$_POST[$itemname]."','".$_POST[$on0]."','".$_POST[$os0]."','".$_POST[$on1]."','".$_POST[$os1]."','".$_POST[$quantity]."','".$invoice."','".$custom."')";
         $result = mysql_query($struery) or die("Cart - paypal_cart_info, Query failed:<br>" . mysql_error() . "<br>" . mysql_errno());

                     }
                }
                else
                {
                     $strQuery = "insert into paypal_payment_info(paymentstatus,buyer_email,firstname,lastname,street,city,state,zipcode,country,mc_gross,mc_fee,itemnumber,itemname,os0,on0,os1,on1,quantity,memo,paymenttype,paymentdate,txnid,pendingreason,reasoncode,tax,datecreation) values ('".$payment_status."','".$payer_email."','".$first_name."','".$last_name."','".$address_street."','".$address_city."','".$address_state."','".$address_zip."','".$address_country."','".$mc_gross."','".$mc_fee."','".$item_number."','".$item_name."','".$option_name1."','".$option_selection1."','".$option_name2."','".$option_selection2."','".$quantity."','".$memo."','".$payment_type."','".$payment_date."','".$txn_id."','".$pending_reason."','".$reason_code."','".$tax."','".$fecha."')";

                     $result = mysql_query("insert into paypal_payment_info(paymentstatus,buyer_email,firstname,lastname,street,city,state,zipcode,country,mc_gross,mc_fee,itemnumber,itemname,os0,on0,os1,on1,quantity,memo,paymenttype,paymentdate,txnid,pendingreason,reasoncode,tax,datecreation) values ('".$payment_status."','".$payer_email."','".$first_name."','".$last_name."','".$address_street."','".$address_city."','".$address_state."','".$address_zip."','".$address_country."','".$mc_gross."','".$mc_fee."','".$item_number."','".$item_name."','".$option_name1."','".$option_selection1."','".$option_name2."','".$option_selection2."','".$quantity."','".$memo."','".$payment_type."','".$payment_date."','".$txn_id."','".$pending_reason."','".$reason_code."','".$tax."','".$fecha."')") or die("Default - paypal_payment_info, Query failed:<br>" . mysql_error() . "<br>" . mysql_errno());
                }

            // send an email in any case
             //echo "Verified";
                mail($notify_email, "VERIFIED IPN", "$res\n $req\n $strQuery\n $struery\n  $strQuery2");
            }
            else 
            {
                // send an email
                mail($notify_email, "VERIFIED DUPLICATED TRANSACTION", "$res\n $req \n $strQuery\n $struery\n  $strQuery2");
            }

            //subscription handling branch
            if ( $txn_type == "subscr_signup"  ||  $txn_type == "subscr_payment"  ) 
            {
                // insert subscriber payment info into paypal_payment_info table
                $strQuery = "insert into paypal_payment_info(paymentstatus,buyer_email,firstname,lastname,street,city,state,zipcode,country,mc_gross,mc_fee,memo,paymenttype,paymentdate,txnid,pendingreason,reasoncode,tax,datecreation) values ('".$payment_status."','".$payer_email."','".$first_name."','".$last_name."','".$address_street."','".$address_city."','".$address_state."','".$address_zip."','".$address_country."','".$mc_gross."','".$mc_fee."','".$memo."','".$payment_type."','".$payment_date."','".$txn_id."','".$pending_reason."','".$reason_code."','".$tax."','".$fecha."')";
                $result = mysql_query($strQuery) or die("Subscription - paypal_payment_info, Query failed:<br>" . mysql_error() . "<br>" . mysql_errno());


                 // insert subscriber info into paypal_subscription_info table
                $strQuery2 = "insert into paypal_subscription_info(subscr_id , sub_event, subscr_date ,subscr_effective,period1,period2, period3, amount1 ,amount2 ,amount3,  mc_amount1,  mc_amount2,  mc_amount3, recurring, reattempt,retry_at, recur_times, username ,password, payment_txn_id, subscriber_emailaddress, datecreation) values ('".$subscr_id."', '".$txn_type."','".$subscr_date."','".$subscr_effective."','".$period1."','".$period2."','".$period3."','".$amount1."','".$amount2."','".$amount3."','".$mc_amount1."','".$mc_amount2."','".$mc_amount3."','".$recurring."','".$reattempt."','".$retry_at."','".$recur_times."','".$username."','".$password."', '".$txn_id."','".$payer_email."','".$fecha."')";
                $result = mysql_query($strQuery2) or die("Subscription - paypal_subscription_info, Query failed:<br>" . mysql_error() . "<br>" . mysql_errno());


                mail($notify_email, "VERIFIED IPN", "$res\n $req\n $strQuery\n $struery\n  $strQuery2");

            }
        }

        // if the IPN POST was 'INVALID'...do this
        else if (strcmp ($res, "INVALID") == 0) 
        {
            // log for manual investigation
            mail($notify_email, "INVALID IPN", "$res\n $req");
        }
    }

    fclose ($fp);
}
?>

What I have noticed that up until the following line, the code is working correctly: mail($notify_email, "IPN Triggered 1", "IPN Triggered 1"); I am receiving this email with the subject line IPN Triggered 1 . So up until this line, its working good.

Once it gets into the while loop, it's not triggering the mails. There is a mail function in if (strcmp ($res, "VERIFIED") == 0) but it's not getting triggered. This was working yesterday, but today it's not!!! None of the mail functions that are within the while loop are triggered.

What can be done to fix this issue so that I can perform both the operations ie write to database and send mails?

EDIT 1:

Ok, I stripped the code that inserts into database & it still behaves the same way. I really feel that PayPal Sandbox is not sending the response. Can anyone please confirm this?

The other half of the code that I modified, looks like this now:

if (!$fp) 
{
    // HTTP ERROR
} 
else 
{

    mail($notify_email, "IPN Triggered 1", "IPN Triggered 1");  

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

    while (!feof($fp)) 
    {
        //Already used this
        //$res = fgets ($fp, 1024);

        //Using this to see if it sends response
        $res = stream_get_contents($fp, 1024);


        if (strcmp ($res, "VERIFIED") == 0) 
        {   
            mail($notify_email, "VERIFIED 1", "VERIFIED 1");

        }
        // if the IPN POST was 'INVALID'...do this
        else if (strcmp ($res, "INVALID") == 0) 
        {
            // log for manual investigation
            mail($notify_email, "INVALID IPN", "$res\n $req");
        }
    }

    fclose ($fp);
}

Solved it. Here's the revised code:

<?php
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$value = preg_replace('/(.*[^%^0^D])(%0A)(.*)/i','${1}%0D%0A${3}',$value);// IPN fix
$req .= "&$key=$value";
}

// post back to PayPal system to validate
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Host: www.sandbox.paypal.com\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n"; 
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

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



if (!$fp) 
{
// HTTP ERROR

} 
else 
{
    fputs ($fp, $header . $req);

    while (!feof($fp)) 
    {
        $res = fgets ($fp, 1024);

        if (strcmp ($res, "VERIFIED") == 0) 
        {
            mail($notify_email, "VERIFIED 1", "VERIFIED 1");

        }
        else if (strcmp ($res, "INVALID") == 0) 
        {

            mail($notify_email, "INVALID IPN", "$res\n $req");
        }
    }

    fclose ($fp);
}
?>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM