Paypal IPN Nightmare - PullRequest
       1

Paypal IPN Nightmare

0 голосов
/ 10 июня 2011

Мне приснился кошмар, пытающийся заставить слушателя Paypal IPN работать должным образом. Код, который у меня есть, выглядит следующим образом (простите за длинный пост кода):

require_once('../Connections/dpp.php');
mysql_select_db($database_dpp, $dpp);


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;
}
}


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

    // If testing on Sandbox use: 
    $header .= "Host: www.sandbox.paypal.com:443\r\n";
//$header .= "Host: www.paypal.com:443\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);
//$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);

// assign posted variables to local variables
$business = @$_POST['business'];
$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'];


if (!$fp) {
    // HTTP ERROR
} else {
fputs ($fp, $header . $req);
    while (!feof($fp)) {
        $res = fgets ($fp, 1024);
        if (strcmp ($res, "VERIFIED") == 0) {
            // Write transaction record to database
            $fecha = date("Y")."-".date("m")."-".date("d");

            $nm=0;
            if ($nm == 0){
                if ($txn_type == "cart"){
                    foreach ($_POST as $key => $value) {
                        $xml .= "    <$key>$value</$key>".PHP_EOL;
                    }

                    $strQuery = "insert into p_paypal_payment_info(paypal_paymentstatus,paypal_buyer_email,paypal_payer_status,paypal_firstname,paypal_lastname,paypal_street,paypal_city,paypal_state,paypal_zipcode,paypal_country,paypal_mc_gross,paypal_mc_fee,paypal_memo,paypal_paymenttype,paypal_paymentdate,paypal_txnid,paypal_pendingreason,paypal_reasoncode,paypal_tax,paypal_datecreation,paypal_verify_sign,paypal_payer_id, paypal_mc_currency,paypal_post_data) values ('".$payment_status."','".$payer_email."','" .$payer_status."','".$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."','".$verify_sign."','".$payer_id."','".$mc_currency."','".$req."')";
                $result_payment = mysql_query($strQuery, $dpp) or die(mysql_error());

                // write individual cart items to database
                for ($i = 1; $i <= $num_cart_items; $i++) {
                    $z_test_qry = "INSERT INTO z_qry_test(qry_id, qry_text) VALUES (NULL, 'cart_items" . $num_cart_items . "')";
                    $result_test = mysql_query($z_test_qry, $dpp) or die(mysql_error());

                     $itemname = "item_name".$i;
                     $itemnumber = "item_number".$i;
                     $mc_handling = "mc_handling".$i;
                     $mc_gross = "mc_gross_".$i;
                     $quantity = "quantity".$i;
                     //CODE GET TO HERE THEN APPEARS TO STOP EXECUTING



                      $strQueryCart = sprintf("insert into p_paypal_cart_info(cart_txnid,cart_itemnumber,cart_itemname,cart_quantity,cart_mc_handling,cart_mc_gross) values (%s, %s, %s, %s, %s, %s)", GetSQLValueString($txn_id, "text"),GetSQLValueString(@$_POST[$itemnumber], "text"),GetSQLValueString(@$_POST[$itemname], "text"), GetSQLValueString(@$_POST[$quantity], "text"), GetSQLValueString(@$_POST[$mc_handling], "text"), GetSQLValueString(@$_POST[$mc_gross], "text"));

                     $result_cart = mysql_query($strQueryCart, $dpp) or die(mysql_error());


                 } // end FOR Loop

                }
            }

            // send mail confirmation to merchant
        }
        else if (strcmp ($res, "INVALID") == 0) {
            // log for manual investigation

            $mail_From = "From: me@mybiz.com";
            $mail_To = "buyer@yourbix.com";
            $mail_Subject = "INVALID IPN";
            $mail_Body = $req;

            foreach ($_POST as $key => $value){
                $emailtext .= $key . " = " .$value ."\n\n";
            }

            mail($mail_To, $mail_Subject, $emailtext . "\n\n" . $mail_Body, $mail_From);

        }
    }
    fclose ($fp);
}

?>

Особенность в том, что если я запускаю этот скрипт локально, передавая содержимое POST в URL и обрабатывая его как GET, он работает нормально. Я могу только предположить, что в коде есть проблема, но я ее не вижу, и, как бы я ни пытался отлаживать обработку (записывая данные и значения переменных в базу данных в качестве стратегических точек), я не могу заставить ее работать. Он достигает примерно трех четвертей пути вниз и угрожает прекратить выполнение (как показано в комментарии в приведенном выше коде). Я точно знаю, что он не выполняет следующую строку, независимо от того, что это такое.

Это основано на скрипте, взятом из генератора скриптов paypaltech.com, поэтому я надеялся, что он будет работать довольно легко.

Кто-нибудь может увидеть, что я делаю не так?

Ответы [ 4 ]

0 голосов
/ 06 марта 2014

Я знаю, что это старый вопрос, но я застрял в аналогичной проблеме, и я вижу ту же ошибку в коде, опубликованном в вопросе.

Пока вы пишете в "ssl: //www.sandbox.paypal.com "часть заголовка" Host "должна по-прежнему читать" www.paypal.com ".

Странно, поскольку их текущий пример не использует часть" Host "В заголовке и старых примерах использовалось то же значение «Хост», что и в домене, используемом в запросе (то же самое, что и значение «Хост» в заголовке).

0 голосов
/ 10 июня 2011

Хорошо, это код, который я использовал из среды песочницы. Код написан на c #, но вы должны быть в состоянии понять идею.

string strSandbox = "https://www.sandbox.paypal.com/cgi-bin/webscr";
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(strSandbox );

            //Set values for the request back
            req.Method = "POST";
            req.ContentType = "application/x-www-form-urlencoded";
            byte[] param = Request.BinaryRead(Request.ContentLength);
            string strRequest = Encoding.ASCII.GetString(param);
            strRequest += "&cmd=_notify-validate";
            req.ContentLength = strRequest.Length;

            //Send the request to PayPal and get the response
            StreamWriter streamOut = new StreamWriter(req.GetRequestStream(), System.Text.Encoding.ASCII);
            streamOut.Write(strRequest);
            streamOut.Close();
            StreamReader streamIn = new StreamReader(req.GetResponse().GetResponseStream());
            string strResponse = streamIn.ReadToEnd();
            streamIn.Close();

            if (strResponse == "VERIFIED")
            {
                var phone = Request.Form["item_number"].ToString();
                var amountPaid = Request.Form["payment_gross"].ToString();

                string credits;
                var temp1 = Request.Form["item_name"].ToString();
                var temp2 = temp1.Split(' ');
                credits = temp2[0].ToString();

                GetPurchaseRequest purchasedetails = new GetPurchaseRequest();
                purchasedetails.AmountPaid = Convert.ToDouble(amountPaid);
                purchasedetails.Credits = Convert.ToInt32(credits);
                purchasedetails.Phone = phone;
                string xmlString = XmlHelper.UploadXmlString<GetPurchaseRequest>(purchasedetails, "Purchase");
            }
            else if (strResponse == "INVALID")
            {
                //log for manual investigation
            }
            else
            {
                //log response/ipn data for manual investigation
            }
0 голосов
/ 11 июня 2011

ОК, переписывание скрипта с нуля, похоже, решило проблему. Единственное, о чем я могу думать, - это то, что исходная версия, возможно, пыталась записать недопустимые типы данных в столбцы в базе данных. Спасибо за помощь, ребята.

0 голосов
/ 10 июня 2011

Чтобы заставить IPN работать, вам нужно включить его из своей учетной записи PayPal.Вы сделали это?

...