PayPal IPN 反复运行

Posted

技术标签:

【中文标题】PayPal IPN 反复运行【英文标题】:PayPal IPN runs repeatedly 【发布时间】:2015-06-09 14:20:12 【问题描述】:

我正在编写一个通过 PayPal 处理付款的 WordPress 插件。我有一个 PayPal IPN 脚本,它会在付款成功时发送电子邮件通知(除了 PayPal 的电子邮件通知)。我的插件的一些用户报告说他们在几天内收到了多份此电子邮件通知。

我在开发插件时很早就发现了这个问题,我找到的解决方案是立即向 PayPal 发送 200 响应。 (这里是对该问题的一些讨论:https://www.paypal-community.com/t5/About-Settings-Archive/Paypal-repeats-identical-IPN-posts/td-p/465559)。这似乎在我的测试站点上运行良好,但显然不适用于我的所有用户。

当我使用 PayPal IPN 模拟器时,它没有给我任何错误消息。

除了立即发送 200 响应之外,我还能做些什么来阻止 PayPal 一遍又一遍地重复 IPN 请求?

这是我的代码:

<?php 

// Create a query var so PayPal has somewhere to go
// https://willnorris.com/2009/06/wordpress-plugin-pet-peeve-2-direct-calls-to-plugin-files
function cdashmm_register_query_var($vars) 
    $vars[] = 'cdash-member-manager';
    return $vars;

add_filter('query_vars', 'cdashmm_register_query_var');


// If PayPal has gone to our query var, check that it is correct and process the payment
function cdashmm_parse_paypal_ipn_request($wp) 
    // only process requests with "cdash-member-manager=paypal-ipn"
   if (array_key_exists('cdash-member-manager', $wp->query_vars) && $wp->query_vars['cdash-member-manager'] == 'paypal-ipn') 

    if( !isset( $_POST['txn_id'] ) ) 
        // send a 200 message to PayPal IPN so it knows this happened
        header('HTTP/1.1 200 OK'); 
        // POST data isn't there, so we aren't going to do anything else
     else 
        // we have valid POST, so we're going to do stuff with it
        // send a 200 message to PayPal IPN so it knows this happened
        header('HTTP/1.1 200 OK'); 

        // process the request.
        $req = 'cmd=_notify-validate';
        foreach($_POST as $key => $value) :
          $value = urlencode(stripslashes($value));
          $req .= "&$key=$value";
        endforeach;

        $header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
        $header .= "Content-Length: " . strlen($req) . "\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Host: www.paypal.com\r\n";
        $header .= "Connection: close\r\n\r\n";
        $fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);

        if(!$fp) 
          // HTTP ERROR
         else 
            fputs ($fp, $header . $req);
            while(!feof($fp)) 

                $res = fgets ($fp, 1024);

                $fh = fopen('result.txt', 'w');
                    fwrite($fh, $res);
                    fclose($fh);

                if (strcmp (trim($res), "VERIFIED") == 0) 

                   /* Do a bunch of WordPress stuff - create some posts, send some emails */

                  

                elseif(strcmp (trim($res), "INVALID") == 0) 
                    // probably ought to do something here

                

            
        fclose ($fp);
        
    


add_action('parse_request', 'cdashmm_parse_paypal_ipn_request');

?>

【问题讨论】:

【参考方案1】:

您无法阻止 Paypal 重复请求。这是 IPN 系统的一部分,以确保即使网站出现故障,交易也能畅通无阻。因此,您应该将此事务 ID 存储在数据库中并检查以确保您过去没有遇到过它。如果您以前遇到过它,您可以记录您看到重复。否则,处理它。

使用 Transactions 类的简单想法:

foreach ($_POST as $key => $value) 
  $value = urlencode(stripslashes($value));
  $req .= "&$key=$value";
  $value = urldecode($value);
  foreach ($pp_vars as $search) 
    if ($key == $search)
      $$key = $value;
  
  if (preg_match("/txn_id/", $key)) 
      $txn_id = $value;
  
  if (preg_match("/item_number/", $key)) 
    $item_number = $value;
  


$model = new Transactions();
if ($model->exists('txid', $txn_id)) 
    $res = "REPEAT";

$model->action[0] = $res;
$model->txid[0] = $txn_id;
$model->description[0] = $req;
$model->price[0] = $payment_gross;
$model->reviewed[0] = 0;
$model->user_id[0] = $user->id;
$model->created_at[0] = date("Y-m-d H:i:s");
$model->updated_at[0] = $model->created_at;
$model->save();    

【讨论】:

谢谢!我实际上已经存储了事务 ID,所以我可以使用一些 WordPress 查询来查看它是否已经存在。

以上是关于PayPal IPN 反复运行的主要内容,如果未能解决你的问题,请参考以下文章

为啥Paypal在使用django-paypal时会重试IPN

为啥 tlstest.paypal.com 可以在浏览器中运行,但不能从我的 PHP 代码中运行(对 Paypal IPN 有用)?

无法接收 PayPal IPN - PayPal 总是收到 403 错误

在 PHP 中使用 IPN 的 Paypal 无法在新的 Beta 开发人员沙箱中运行

Paypal 支付按钮和 IPN:如何唯一地链接用户?

PayPal IPN 变量问题