贝宝 IPN 失败

Posted

技术标签:

【中文标题】贝宝 IPN 失败【英文标题】:Paypal IPN failure 【发布时间】:2013-07-18 08:46:03 【问题描述】:

我已设置 Paypal 帐户通知 URL 以转到此脚本:

    // Read the notification from PayPal which comes in the form of a POST array and create the acknowledgement response
    $req = 'cmd=_notify-validate';               // add 'cmd' to beginning of the acknowledgement you send back to PayPal

    foreach ($_POST as $key => $value) 
     // Loop through the notification NV pairs
    $value = urlencode(stripslashes($value));  // Encode the values
    $req .= "&$key=$value";                    // Add the NV pairs to the acknowledgement
    


    // Assign the paypal payment notification values to local variables
    if($_POST)
    $item_name = $_POST['item_name'];
    $item_number = $_POST['item_number'];
    $payment_status = $_POST['payment_status'];
    $payment_amount = $_POST['mc_gross'];
    $payment_currency = $_POST['mc_currency'];
    $txn_id = $_POST['txn_id'];
    $receiver_email = $_POST['receiver_email'];
    $payer_email = $_POST['payer_email'];

    //Set up the acknowledgement request headers (this is the updated version for http 1.1)
    $header .= "POST /cgi-bin/webscr HTTP/1.1\r\n";
    $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $header .= "Host: www.paypal.com\r\n";
    $header .= "Connection: close\r\n";
    $header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
    //Open a socket for the acknowledgement request
    $fp = fsockopen ('www.paypal.com', 80, $errno, $errstr, 30);

    if(!$fp)
        echo "HTTP ERROR";
    
    else
    //start 1

    // Post request back to PayPal for validation
    fputs ($fp, $header . $req);

    //once paypal receives the acknowledgement response, another message will be send containing the single word VERIFIED or INVALID

    while (!feof($fp)) 
         //start 2, while not EndOfFile
    $res = fgets ($fp, 1024); // Get the acknowledgement response
    $res = trim($res);
        if (strcmp ($res, "VERIFIED") == 0) 
            // start 3, Response is OK

            if ($payment_status == "Completed")
                //start 4

                //send email announcing success

                $from = "Rupert Heath Literary Agency";
                $to = $payer_email;
                $subject = "Ebook";
                $body = "It works";
                mail($to, $subject, $body, $from);

                //end 4
            //end 3
            else if(strcmp ($res, "INVALID") == 0)
                //start 5

                //send email announcing failure
                //$error_log .= 'Line 57'

                $from = "Guide Test Page";
                $to = $payer_email;
                $subject = "INVALID IPN";
                $body = "Doesn't work";
                mail($to, $subject, $body, $from);
                //end 5


     //end 2
fclose ($fp);  //close file pointer
 //end 1

它基于许多网络托管示例,适合升级到 HTTP 1.1

脚本作为测试,根据来自 Paypal 的 VERIFIED 或 INVALID 响应发送成功或失败电子邮件。问题是我总是收到一封无效的电子邮件并且不明白为什么。我查看了 Paypal IPN 历史记录,HTTP 响应代码为 200,这似乎表明 IPN 交换工作正常,因此 Paypal 可能正在响应 VERIFIED 但我的脚本有错误。

IPN 历史详情如下:

即时付款通知 (IPN) 详细信息

消息 ID69025489S2598613V

创建日期/时间 18/07/2013 23:22 PDT

原件/重新发送原件

最近的交付尝试日期/时间 18/07/2013 23:22 PDT

通知网址http://www.rupertheath.com/ipn/ipn_script

HTTP 响应代码 200

发送状态已发送

没有。重试次数 0

事务 ID4D0877596N038120Y

IPN 类型交易完成

IPN 消息 mc_gross = 0.01 protection_eligibility =合格&address_status =证实与payer_id = C3USV8A4Q2QDW&税= 0.00&address_street =拉姆齐家34福勒斯路与PAYMENT_DATE = 23:22:44 2013年7月18日PDT&PAYMENT_STATUS =完成和字符集=窗口1252&address_zip = SP1 2QU&FIRST_NAME =迈克尔&mc_fee = 0.01 address_country_code = GB&ADDRESS_NAME =迈克尔·希思&notify_version = 3.7&custom=&payer_status=verified&business=emailagency@rupertheath.com&address_country=United王国&ADDRESS_CITY =梳&量= 1&verify_sign = AhKyCHsfiy2frgZNNoQmGHQ3LhKMAboweJqZzYCdqp30Hb7b99tF.04a&PAYER_EMAIL = msheath @ btinternet.com&txn_id = 4D0877596N038120Y&payment_type =即时&姓氏=希斯&ADDRESS_STATE =威尔特&RECEIVER_EMAIL = emailagency @ rupertheath.com&payment_fee =&receiver_id = BRM2TYMP4ACZ8&txn_type = web_accept&ITEM_NAME = Ebook&mc_currency=GBP&item_number=&residence_country=GB&handling_amount=0.00&transaction_subject=Ebook&payment_gross=&shipping=0.00&ipn_track_id=b0a3b4ae3c51c

谁能帮我调试一下这个问题?

【问题讨论】:

你从哪里得到的验证码? Paypal 有一个 IPN 历史页面,如果您点击一个特定的 IPN 事件,您将获得所有这些数据。从数据看来,Paypal 认为一切正常,所以我对我的脚本持怀疑态度,尽管我已经检查了一百次! 【参考方案1】:

最好使用原始发布的数据,而不是自己重建。这是我个人使用的代码,到目前为止运行良好:

file_get_contents(
    'https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate',
    false,
    stream_context_create(array(
        'http'=>array(
            'method'=>'POST',
            'header' => 'Content-Type: application/x-www-form-urlencoded',
            'content' => file_get_contents('php://input'),
        )
    ))
);

它也可以很容易地变成 cURL。

【讨论】:

谢谢你,这可能是一个改进,但我的脚本很标准,网上有几十个例子,基本上都是一样的,为什么它对我不起作用?跨度> @Perkin5 基本上我不相信任何东西,一旦被 PHP 解析,就会再次成为原始字符串;抱歉,我不能确切地告诉你为什么你的脚本不起作用。【参考方案2】:

这行很可能是个问题:

$value = urlencode(stripslashes($value));

具体来说,在那里使用stripslashes。如果你的 PHP 配置有(上帝帮助你)Magic Quotes,你只需要包含stripslashes。值得庆幸的是,自 PHP 5.4 起,Magic Quotes 已被删除,因此您可以安全地从该行中删除 stripslashes,使其成为:

$value = urlencode($value);

信不信由你,Paypal 允许用户数据包含反斜杠。因此,如果 IPN 有任何反斜杠,并且您使用 stripslashes 将其删除,当您将 IPN 数据发回 PayPal 进行验证时,Paypal 会给您 INVALID 响应,因为数据不匹配。

【讨论】:

以上是关于贝宝 IPN 失败的主要内容,如果未能解决你的问题,请参考以下文章

Paypal IPN 和 wordpress 失败

为暂停的订阅正确的贝宝 IPN 变量

贝宝自适应 API

IPN 验证在应该失败时不会失败

是啥导致我的 PayPal IPN 脚本失败?

重试失败付款时,PayPal 是不是使用相同的交易 ID?