【问题标题】:Paypal IPN Nightmare贝宝 IPN 噩梦
【发布时间】:2011-09-12 16:19:27
【问题描述】:

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

?>

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

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

谁能看出我做错了什么?

【问题讨论】:

  • 较小的非明显错误:PHP 中的'0' == '',因此您的代码会将合法的零转换为空值。您需要使用严格的比较运算符(!=====)来检查空字符串。
  • 好地方,虽然这不会导致我遇到的问题......
  • 没有。我建议在事情似乎死去的地方吐出你正在构建的查询的文本,以及一些 echo 'got to stage XXX' 类型的调用,这样你就可以准确地看到事情在哪里死去。
  • 是的,我就是这么想的。由于该脚本由 PHP 调用并且从未在前端呈现,因此我一直在相关点将内容写入数据库。我在$strQueryCart = 行之后直接添加了一行来执行此操作,并且它永远不会被执行。这是我想不通的……
  • 虽然在 $strQueryCart = 行之前执行完全相同的语句确实执行 - 去看看!

标签: php paypal paypal-ipn


【解决方案1】:

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

【讨论】:

  • 是的 - 代码一直工作到代码中指示的点。这不是贝宝配置问题。
  • jray0039,这不是真的。您也可以在 SetExpressCheckout 中使用 notify_url(网站支付标准)/ NOTIFYURL 来启动 IPN(尽管如果您的帐户禁用了 ipn,这将不起作用。)
  • 看看我在stackoverflow.com/questions/9369069/… 中的回答,它解释了 PayPal 中 IPN 的各种状态以及如何通过 PayPal 配置文件或通过在 API 调用中传递某些参数来控制它。
【解决方案2】:

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

【讨论】:

  • 谢谢你,但我认为这不会有帮助。我现在已经编写了三个独立的 IPN 帮助脚本,所有这些都由我的沙盒帐户处理。唯一不起作用的是我上面帖子中的那个。另外两个(只是发送电子邮件,不写入数据库)工作得很好。
  • 好的。我希望我能提供更多帮助,但自从我用 php 编写代码以来已经有一段时间了。我确实看到您的 sn-p 中有很多代码。我会先让它非常基础。让它与基本代码一起工作并从那里构建,直到你找到它中断的地方。然后你就可以解决真正的问题了。我知道这是一般帮助,但这是我解决 90% 自己问题的方法:)
  • 正是我现在正在做的事情。讨厌倒退,但认为我别无选择。如果我解决了问题,将在此处发布。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

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

    当您发布到“ssl://www.sandbox.paypal.com”时,标题的“主机”部分仍必须为“www.paypal.com”。

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

    【讨论】:

      猜你喜欢
      • 2011-10-20
      • 2015-06-16
      • 2016-05-09
      • 2023-03-11
      • 2014-04-24
      • 2012-08-19
      • 2012-08-15
      • 2014-08-25
      • 2013-07-10
      相关资源
      最近更新 更多