Paypal IPN梦魇

时间:2011-06-10 17:10:44

标签: php paypal paypal-ipn

我正在做一个噩梦,试图让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);
}

&GT;

奇怪的是,如果我在本地运行此脚本,在URL中传递POST的内容并作为GET处理,它可以正常工作。我只能假设代码中存在问题,但我无法看到它,并且我尝试调试处理(通过将数据和变量值作为战略要点写入数据库)我无法让它工作。它达到了大约四分之三的位置,并且可能会停止执行(由上面代码中的注释引导)。我知道它不会执行以下行,无论它是什么。

这是基于从paypaltech.com脚本生成器中获取的脚本,所以我希望它可以很容易地工作。

谁能看到我做错了什么?

4 个答案:

答案 0 :(得分:0)

要使IPN正常工作,您需要在paypal帐户中启用它。你做过这个吗?

答案 1 :(得分:0)

好的,这是我在沙箱环境中使用的代码。代码在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
            }

答案 2 :(得分:0)

好的,从头开始重写脚本似乎解决了这个问题。我唯一能想到的是原始版本可能一直在尝试将无效数据类型写入数据库中的列。谢谢你的帮助。

答案 3 :(得分:0)

我知道这是一个老问题,但我遇到了类似的问题,我可以在问题中发布的代码中看到相同的错误。

虽然您要发布到“ssl://www.sandbox.paypal.com”,但标题中的“主持人”部分仍必须显示为“www.paypal.com”。

奇怪,因为他们当前的示例不使用标题的“主机”部分,而旧示例用于使用与请求中使用的域相同的“主机”值(这与不包括“主机“标题中的值”。