Paypal IPN 现在 returns 无效 - PHP 以前工作正常的代码

Paypal IPN now returns INVALID - PHP code previously working fine

我正在使用以下 class 来处理 IPN 数据: https://github.com/WadeShuler/PHP-PayPal-IPN(多年来一直运行良好)

最后一次成功处理的付款是在 9 月 28 日,下一次 IPN 付款是在 10 月 5 日收到的,返回无效响应,此后的每笔付款都是如此。

如果我在 IPN 模拟器中测试,消息处理成功。 Sandbox 或 Live,响应无效。我原以为 Sandbox 会有一个工具,我可以在其中查看为什么消息被拒绝为无效,但情况似乎并非如此?肯定是查看拒绝原因的简单方法,我错过了什么吗?

将您从我的网站带到 Paypal 的 link 是:

https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_ext-enter&redirect_cmd=_xclick&business=sales-facilitator@fydentry.com&item_name=QLD++%28Pacific+pines+secondary+Sat+25th+July+%29&item_number=FYD15000003&custom=0001000003&currency_code=AUD&amount=0.01&no_shipping=1&image_url=http://www.fydentry.com/img/follow-your-dreams-100.jpg&return=http://www.fydentry.com/entry-test.php&cancel_return=http://www.fydentry.com/entry-test.php&notify_url=http://www.fydentry.com/payback-test.php

从 Paypal 返回的数据 post 是:

transaction_subject=0001000003&txn_type=web_accept&payment_date=07%3A05%3A07+Oct+15%2C+2015+PDT&last_name=buyer&residence_country=AU&pending_reason=multi_currency&item_name=QLD++%28Pacific+pines+secondary+Sat+25th+July+%29&payment_gross=&mc_currency=AUD&business=sales-facilitator%40fydentry.com&payment_type=instant&protection_eligibility=Ineligible&verify_sign=Acssfl2b2v1gxOK33TD2StcDhf-OAZxwix74kxFlSgpWMku6myuy.WFL&payer_status=verified&test_ipn=1&tax=0.00&payer_email=sales-buyer%40fydentry.com&txn_id=9BV63134E20871700&quantity=1&receiver_email=sales-facilitator%40fydentry.com&first_name=test&payer_id=FY3RYW98GNMXG&receiver_id=95FC3QCK53MHC&item_number=FYD15000003&handling_amount=0.00&payment_status=Pending&shipping=0.00&mc_gross=0.01&custom=0001000003&charset=windows-1252&notify_version=3.8&ipn_track_id=cfbd422d97d69

我发回 Paypal 的回复是:

cmd=_notify-validate&transaction_subject=0001000003&txn_type=web_accept&payment_date=07%3A05%3A07+Oct+15%2C+2015+PDT&last_name=buyer&residence_country=AU&pending_reason=multi_currency&item_name=QLD++%28Pacific+pines+secondary+Sat+25th+July+%29&payment_gross=&mc_currency=AUD&business=sales-facilitator%40fydentry.com&payment_type=instant&protection_eligibility=Ineligible&verify_sign=Acssfl2b2v1gxOK33TD2StcDhf-OAZxwix74kxFlSgpWMku6myuy.WFL&payer_status=verified&test_ipn=1&tax=0.00&payer_email=sales-buyer%40fydentry.com&txn_id=9BV63134E20871700&quantity=1&receiver_email=sales-facilitator%40fydentry.com&first_name=test&payer_id=FY3RYW98GNMXG&receiver_id=95FC3QCK53MHC&item_number=FYD15000003&handling_amount=0.00&payment_status=Pending&shipping=0.00&mc_gross=0.01&custom=0001000003&charset=windows-1252&notify_version=3.8&ipn_track_id=cfbd422d97d69

payback-test.php中的代码是:

<?php
  include_once("f_common.php");
  include_once("IpnListener.php");

  use wadeshuler\paypalipn\IpnListener;

  $listener = new IpnListener();
  $listener->use_sandbox = true;
  $dbh = open_db();

  $res = 'UNKNOWN';

  try {
    $listener->requirePostMethod();
    $verified = $listener->processIpn();
  } catch (Exception $e) {
    error_log($e->getMessage());
    exit(0);
  }


  if ($verified) {
      $res = "VERIFIED";
  } else {
      $res = "INVALID";
    }

  $stmt_debug = $dbh->prepare('INSERT INTO fyd_paypal_ipn (post_data, response_data, status, message_time) VALUES (:post_data, :response_data, :status, UTC_TIMESTAMP())');
  $stmt_debug->execute(array(':post_data' => $listener->rawPostData, ':response_data' => $listener->debug_response, ':status' => $res));
?>

请注意,出于本练习的目的,我还修改了 IpnListener class,以便我可以获得响应的副本以进行调试。

在文件顶部的变量声明中,我制作了 $rawPostData public,并添加了这个变量:

public $debug_response;

并在我们使用之前存储该值:

        $this->debug_response = $req;

        if ($this->use_curl) {
            $res = $this->curlPost($req);
        } else {
            $res = $this->fsockPost($req);
        }

我假设 Paypal 方面发生了一些变化,首先停止了这项工作,但我看不出它是什么,特别是因为我的回答似乎是正确的(相同的),而且我可以在 Sandbox 端找到任何可以帮助我确定为什么它被视为无效的东西?不幸的是,我跟踪 IPN post 数据和响应的底部调试代码是新的,所以我没有较旧的(有效!)消息集来比较内容。

我已经弄清楚了,这似乎是一个证书问题,同时还有一个脚本错误。

我的证书文件与 Wade 代码中当前的文件相比已过时。我昨天发现并更新了证书文件。我现在已经证实这是我最初失败的根本原因。

然而,在更新它的同时,我也更新到最新的 class - 这实际上只是删除了一些我没有使用并且不再受支持的已弃用代码,但我错过了一个小改动弄坏了东西。

IpnListener class 中有一行设置证书位置:

curl_setopt($ch, CURLOPT_CAINFO, dirname(dirname(__FILE__)) . '/cert/api_cert_chain.crt');

但是在我的服务器上目录名称最终是错误的,并且找不到证书。 class 的上一版本为:

curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cert/api_cert_chain.crt');

有效。现在我把它改回来了,一切都恢复正常了。请注意,我正在使用的域是在我的主域的子目录中设置的,这可能是新代码最终指向错误位置(比我需要的位置高一级)的原因。

我仍然不明白为什么 IPN 模拟器可以工作,而 Sandbox 和 Live 系统却不能。

hummmm,自 10 月 1 日起,paypal 将 sha-1 更改为 sha-2 https://www.paypal-knowledge.com/infocenter/index?page=content&id=FAQ1766&expand=true&locale=en_US