4

我已经在这工作了 24 小时,现在正要拔掉我的头发。我已经检查了整个 Web 和 Stackoverflow,但找不到任何帮助。我什至检查过以前的帖子,例如没有收到来自 Paypal IPN 沙盒的回复,但这些回复对我不起作用。也许我错过了对我有帮助的帖子;如果我有,请原谅我重复同样的问题,但这件事相当紧急,我已经走到尽头了。

无论如何,问题是这样的:

我有一个 PHP 购物车,它将客户发送到 Paypal。一切正常。在向他们发送所有代码时,我已经按照 Paypal 的说明构建了它。一切都很好,除了最后一步,POST从 Paypal 返回到我的服务器以检查一切正常。即使在那里,我也照原样复制了整个 Paypal 代码,并添加了检查我的所有匹配项的功能。但是,我无法让它工作。我尝试将结果发送到数据库,但没有任何反应。Mail因此,如果一切正常并且我没有收到电子邮件,我将一个 PHP命令放在最后一个操作应该在的位置。我Mail几乎在其他任何地方都放置了同样的命令,试图找出什么'

首先,当我调用将 Paypal 应该发送回我的服务器的 vars 打印到电子邮件中时,我收到了包含除item_nameand之外的所有 vars 的电子邮件item_number,我得到了空白;这很奇怪,因为到目前为止,Paypal Sandbox 正在向我展示我应该购买的每一件产品。我试着给 PHP 代码上的这些变量一个固定的值,因为 Paypal 没有向它们发布值,至少在那时。我想看看缺少这两个值是否是错误的原因;但是,即使使用设定值,错误仍然存​​在。

其次, Paypal 代码中有一个while循环(上面给出的链接中的响应说应该替换为 的循环$res=stream_get_contents($fp, 1024);,但是,这对我也不起作用),所以我把Mail命令放在那里看看我回来了。我要求打印$resvar 和 the payment_status,果然得到了几封 E-Mail,收集到的结果如下:

    payment_status = Pending
    $res = HTTP/1.0 302 Found
           Location: https://www.sandbox.paypal.com
           Server: BigIP
           Connection: close
           Content-Length: 0

所以我猜这个错误正在发生。有些事情正在发生(或没有发生),它不仅没有返回代码为继续检查等而寻找的Completed状态payment_status,而且甚至没有返回INVALID响应。所以我没有得到任何回应,也没有任何东西可以告诉我一切是否正常。而且,奇怪的是,甚至更糟糕的是,Sandbox 仍然在每次付款尝试都向我收取虚假费用,即使很明显某处存在错误并且流程没有完成。(当然,这带来了另一个困境:一旦这一切都解决了,如果由于 X 原因在某个时候出现服务器错误,Paypal 是否仍会向我的客户收费,我赢了'

好吧,我想这就是我在这件事上所能解释的。在这一点上,我看不出我哪里出错了。代码应该使这变得非常简单。所以我真的不明白我怎么能搞砸复制和粘贴。我想至少应该没有错误,除非它们带有原始代码。此外,因为在那一点上其他一切都 100% 正常工作,所以这个错误可能出现的唯一地方是这个 PHP 文件中,一旦用户完成支付过程,Paypal 就必须调用它。

任何关于此事的想法将不胜感激!

这里是代码。

PHP代码:

    include('../inc/db_fns.inc'); //<--All my DB work is in here.
    include('../inc/shipping.inc');

    $paypal_email = "seller_1360198925_biz@hotmail.com";
    $paypal_currency = 'USD';

    //Here begin the functions I'm using to check everything and pass data to DB.
    function no_paypal_trans_id($trans_id) {
      $connection = db_connect();
      $query = sprintf("SELECT id FROM orders WHERE paypal_trans_id = '%s'", mysql_real_escape_string($trans_id));
      $result = mysql_query($query);
      $num_results = mysql_num_rows($result);
      if($num_results == 0) {
        return true; 
      }
      return false;
    }

    function payment_amount_correct($shipping, $params) {
      $amount = 0.00;   
      for ($i=1;  $i <= $params['num_cart_items']; $i++) {
        $query = sprintf("SELECT precio FROM products WHERE id='%s'", mysql_real_escape_string($params["item_number{$i}"]));
        $result = mysql_query($query);
        if($result) {
          $item_price = mysql_result($result, 0, 'precio');
          $amount += $item_price * $params["quantity{$i}"];
        }
      }
      if(($amount+$shipping) == $params['mc_gross']) {
        return true;    
      } else {
        return false;   
      }
    }

    function create_order($params) {
      db_connect();
      $query =  sprintf("INSERT INTO orders set orders.firstname = '%s', orders.lastname = '%s', orders.email = '%s', orders.country = '%s', orders.address = '%s', orders.city = '%s', orders.zip_code = '%s', orders.state = '%s', orders.status = '%s', orders.amount = '%s', orders.paypal_trans_id = '%s', created_at = NOW()", mysql_real_escape_string($params['first_name']), mysql_real_escape_string($params['last_name']), mysql_real_escape_string($params['payer_email']), mysql_real_escape_string($params['address_country']), mysql_real_escape_string($params['address_street']), mysql_real_escape_string($params['address_city']), mysql_real_escape_string($params['address_zip']), mysql_real_escape_string($params['address_state']), mysql_real_escape_string($params['payment_status']), mysql_real_escape_string($params['mc_gross']), mysql_real_escape_string($params['txn_id']));
      $result = mysql_query($query);
      if(!$result) {
        return false;
      }
      $order_id = mysql_insert_id();
      for ($i=1;  $i <= $params['num_cart_items'] ; $i++) {
        $product = find_product($params["item_number{$i}"]);
        $query = sprintf("INSERT INTO items set order_id = '%s', product_id = '%s', title = '%s', price = '%s', qty = '%s'", mysql_real_escape_string($order_id), mysql_real_escape_string($product['id']), mysql_real_escape_string($product['title']), mysql_real_escape_string($product['price']), mysql_real_escape_string($params["quantity{$i}"]));
        $result = mysql_query($query);
        if(!$result) {
          return false; 
        }
      }
      return true;
    }   

    //Here begins the Paypal code as is
    // 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";
    $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
    $fp = fsockopen ('www.sandbox.paypal.com', 80, $errno, $errstr, 30); //<--Here I also tried out the other response to the question linked above and it actually returned a 'Invalid host' into he $res var-

    // assign posted variables to local variables
    $item_name = $_POST['item_name'];    //<--These are the two vars for which
    $item_number = $_POST['item_number'];//   Paypal Sandbox posts no value.
    $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'];

    if (!$fp) {
      // HTTP ERROR
    } else {
      fputs ($fp, $header . $req);
      while (!feof($fp)) {
        $res = fgets ($fp, 1024);
        if (strcmp ($res, "VERIFIED") == 0) {
        if ($_POST['payment_status'] == 'Completed' && no_paypal_trans_id($_POST['txn_id']) && $paypal_email == $_POST['receiver_email'] && $paypal_currency == $_POST['mc_currency'] && payment_amount_correct($shipping, $_POST)) {
            // process payment
            create_order($_POST);
          }
        } else if (strcmp ($res, "INVALID") == 0) {
          // log for manual investigation
        }
      }
      fclose ($fp);
    }

编辑1:再试一次:不走运!

我刚刚尝试了原始的、未改动的 Paypal 代码。我刚刚将它复制并粘贴到这个 PHP 中,然后运行 ​​Sandbox 购买。同样的结果。没有回应,没有数据插入表格,我无法知道有人真的从我的购物车上买了东西,但 Paypal 仍然对购买进行虚假收费。这支持了我的怀疑,即错误出现在原始代码中,与我添加的函数无关。希望有人能尽快理解这一点。千提前感谢那个人!

编辑 2:在第一个响应之后。

现在删除了他/她的回复的好心用户非常好心,可以先尝试一下。他/她建议在 Paypal 文档中提及https://www.sandbox.paypal.com/cgi-bin/webscr我拥有的http://www.sandbox.paypal.com. 也许我有旧版本的代码,所以我尝试了他/她的建议。现在我评论发生了什么:

首先,非常感谢您的回复。不幸的是,没有运气。用另一个地址替换了一个地址,现在该过程没有进入while循环,它停止在fsockopen. 我放置了一个Mail命令来打印出该命令中包含的$errno$errstrhttps://www.sandbox.paypal.com/cgi-bin/webscr替换后http://www.sandbox.paypal.com无法找到套接字传输“https” - 您在配置 PHP 时是否忘记启用它?所以我剥离了“https://”并再次尝试。现在我得到php_network_getaddresses: getaddrinfo failed: Name or service not known。有任何想法吗?

编辑 3:在评论部分与@hexacyanide 交谈后:

    $req = cmd=_notify-validate&test_ipn=1&payment_type=instant&payment_date=20%3A55%3A22+Feb+08%2C+2013+PST&payment_status=Completed&address_status=confirmed&payer_status=verified&first_name=John&last_name=Smith&payer_email=buyer%40paypalsandbox.com&payer_id=TESTBUYERID01&address_name=John+Smith&address_country=United+States&address_country_code=US&address_zip=95131&address_state=CA&address_city=San+Jose&address_street=123%2C+any+street&receiver_email=seller%40paypalsandbox.com&receiver_id=TESTSELLERID1&residence_country=US&item_name1=something&item_number1=AK-1234&quantity1=1&tax=2.02&mc_currency=USD&mc_fee=0.44&mc_gross_1=9.34&mc_handling=2.06&mc_handling1=1.67&mc_shipping=3.02&mc_shipping1=1.02&txn_type=cart&txn_id=2229455&notify_version=2.4&custom=xyz123&invoice=abc1234&charset=windows-1252&verify_sign=AsdNkKD2ktCz.aUB.9WYWy-g8MHoAa-TsvSjUgGstseJVdUhQTq3aCwW

对不起,那是$req,不是$resvar。$resvar 由循环while返回。我在那里放置了一个命令,我收到了几封带有这些值mail的电子邮件。$res这些都是:

    X-Frame-Options: SAMEORIGIN
    HTTP/1.0 200 OK
    Strict-Transport-Security: max-age=14400
    INVALID 
    Content-Type: text/html; charset=UTF-8
    Date: Sat, 09 Feb 2013 05:44:33 GMT
    Connection: close
    Content-Length: 7

编辑 4:绝对目瞪口呆:即使是直接来自 Paypal 开发者网站并使用 Paypal 开发者网站 IPN 测试器进行测试的简单 Paypal IPN 代码也不能工作......

  1. 我使用了此处找到的 Paypal IPN 脚本生成器。
  2. 我选择生成一个脚本,该脚本将向我发送一个 VALID 或 INVALID 响应。
  3. 我将其全部复制并粘贴到我保存在服务器中的 PHP 文件中。
  4. 我检查并重新检查了代码的任何部分都没有留下。
  5. 我从这里找到的 IPN 模拟器将这个 PHP 文件定位在我的服务器上。
  6. 模拟器显示检查并显示“ IPN 已成功发送。
  7. 我去查看我的邮件,看看我收到了什么回复,是有效的还是无效的……我根本没有收到任何回复。因此,IPN 在某些时候到达 PHP 购买,该过程被破坏,因此它甚至无法访问 VALID/INVALID 函数。然而,这正是 Paypal 为您提供的代码,并使用它为其设计的 sim 卡进行了测试。发生什么了?

这次奥德赛的第二天

OK 不用说:还没有运气。但我现在决定详尽地跟踪进入 PHP 代码并输出到 Paypal 的所有内容。这个想法是,VALID当此代码以相同的顺序将 Paypal 插入其中的初始值发送回 Paypal 时,会发生响应(根据 Paypal 文档)。

第一个问题是我没有收到任何来自代码的响应。所以假设是代码在一开始就失败了。碰巧第一个问题是沙盒链接不起作用。(我在@hexacyanide 的帮助下做到了这一点,他昨天很乐意跟随我的进步或缺乏。每当我获得足够的声誉来积极地标记他/她的回应时,我会的。)所以我剥离了sandbox.而且,瞧,它正在返回一个响应,但现在响应是INVALID.

从那时到现在,我了解到 IPN 仅用于卖方交易检查和数据记录。Paypal 不关心 IPN 的结果。所以我的购物车是 100% 工作的。用户可以购买东西,Paypal 会向用户收费。如果购买信息实际上来自 Paypal 并且一切正常,IPN 只会为我检查,然后(在我的脚本中)将所有这些信息发送到数据库中,以便我可以完成我的服务。因此,即使交易在没有 IPN 的情况下成功进行,IPN 仍将是促进整个销售过程的宝贵机制。但是,所有这些最后的信息都解决了我的怀疑,即我所有的购物车代码都正常,问题仅出在此处,使用此代码或 Paypal 处理它的方式。(Paypal 的“处女”代码通过 Paypal 的事实

所以,所有进出这个 PHP 的日志。为了创建检查点,我Mail在代码中的每个重要点都放置了命令。在foreach()命令中,我包含了一个增量变量,以便获得进入的 POSTED 数据的有序列表。这就是我得到的:

这是 Paypal 发布到代码中的数据(按照发布的顺序)

    test_ipn=1
    payment_type=instant
    payment_date=08%3A42%3A23+Feb+09%2C+2013+PST
    payment_status=Completed
    payer_status=verified
    first_name=John
    last_name=Smith
    payer_email=buyer%40paypalsandbox.com
    payer_id=TESTBUYERID01
    business=seller%40paypalsandbox.com
    receiver_email=seller%40paypalsandbox.com
    receiver_id=TESTSELLERID1
    residence_country=US
    item_name1=something
    item_number1=AK-1234
    quantity1=1
    tax=2.02
    mc_currency=USD
    mc_fee=0.44
    mc_gross=15.34
    mc_gross_1=12.34
    mc_handling=2.06
    mc_handling1=1.67
    mc_shipping=3.02
    mc_shipping1=1.02
    txn_type=cart
    txn_id=23291642
    notify_version=2.4
    custom=xyz123
    invoice=abc1234
    charset=windows-1252

乍一看,我似乎从 Paypal 获得了我应该得到的所有数据。这是PP发送它的顺序。所以如果我按这个顺序发回这个数据,而 PP 实际上确实检查了这个相同的顺序,那么理论上我应该得到一个VALID响应。

所以代码所做的是添加“cmd=_notify-validate”,这是唯一的添加(PP 文档明确指出这是必要的添加是必要的),并将所有这些数据传递到$req以这种方式调用的 var 中:A=X&B=Y&C=Z....

这是来自下一个检查点的消息,在foreach()命令关闭后添加。

    $req = cmd=_notify-validate&test_ipn=1&payment_type=instant&payment_date=08%3A42%3A23+Feb+09%2C+2013+PST&payment_status=Completed&payer_status=verified&first_name=John&last_name=Smith&payer_email=buyer%40paypalsandbox.com&payer_id=TESTBUYERID01&business=seller%40paypalsandbox.com&receiver_email=seller%40paypalsandbox.com&receiver_id=TESTSELLERID1&residence_country=US&item_name1=something&item_number1=AK-1234&quantity1=1&tax=2.02&mc_currency=USD&mc_fee=0.44&mc_gross=15.34&mc_gross_1=12.34&mc_handling=2.06&mc_handling1=1.67&mc_shipping=3.02&mc_shipping1=1.02&txn_type=cart&txn_id=23291642&notify_version=2.4&custom=xyz123&invoice=abc1234&charset=windows-1252&verify_sign=AFcWxV21C7fd0v3bYYYRCpSSRl31ACyRxUQ6LVDwUz.i78mjQLsN9aKb

注意最后verify_sign=AFcWxV21C7fd0v3bYYYRCpSSRl31ACyRxUQ6LVDwUz.i78mjQLsN9aKbforeach()我无法解释那段数据,因为它在循环期间没有以电子邮件的形式吐出。那么它是从哪里来的呢?INVALID这可能是返回响应的罪魁祸首吗?开放式问题。但是此时,所有这些数据都由代码在“ DATA COMING IN ”检查点传递;所以如果这个数据是进来的,我的代码把它发回,那么一切都应该没问题。

所以下一个检查点将是“ DATA COMING OUT ”。fputs ($fp, $header . $req);我在写$req回 PP的代码之前找到了这个检查点。这就是代码的结果:

    $req = cmd=_notify-validate&test_ipn=1&payment_type=instant&payment_date=08%3A42%3A23+Feb+09%2C+2013+PST&payment_status=Completed&payer_status=verified&first_name=John&last_name=Smith&payer_email=buyer%40paypalsandbox.com&payer_id=TESTBUYERID01&business=seller%40paypalsandbox.com&receiver_email=seller%40paypalsandbox.com&receiver_id=TESTSELLERID1&residence_country=US&item_name1=something&item_number1=AK-1234&quantity1=1&tax=2.02&mc_currency=USD&mc_fee=0.44&mc_gross=15.34&mc_gross_1=12.34&mc_handling=2.06&mc_handling1=1.67&mc_shipping=3.02&mc_shipping1=1.02&txn_type=cart&txn_id=23291642&notify_version=2.4&custom=xyz123&invoice=abc1234&charset=windows-1252&verify_sign=AFcWxV21C7fd0v3bYYYRCpSSRl31ACyRxUQ6LVDwUz.i78mjQLsN9aKb

哼!我错过了什么吗?我的眼睛是否跳过了导致此代码旅行的最微小的打嗝?输出似乎与输入完全相同。让我们假设 PP 很好地处理了他们的代码,POST 数据以 PP 期望的方式转换为字符串,因此,检查......假设所有这些,可能有什么问题?

让我们再看一遍:开放式问题:

  • 会不会是标题的问题?根据文档,这是应该使用的标题......所以除非他们对此关闭,否则它应该可以正常工作。
  • 给定的 URL 可能有问题吗?好的,这实际上是一个问题,或者更确切地说是在某些时候。互联网上至少有 6 或 7 个不同的 URL,它们应该可以工作,但不能工作。有些人为某些人工作而不为其他人工作,有些人似乎永远不会工作,等等。甚至 PP 自己也不确定应该使用什么 URL,因为在他们自己的文档中它会有所不同。很清楚的是,使用sandbox.URL 将不会返回任何内容——假设这些 URL 已损坏。
  • 可能是字符集的问题吗?会不会有不兼容?当我看到数据以十六进制代码进出时,我突然想到了这一点。问题是这应该使它兼容,对吧?然而,昨天,当我检查while()循环中发生了什么,并将从 PP 发回的信息捕获到$resvar 中时,我没有得到十六进制代码,正如你在本遗嘱中进一步看到的那样。

下一个检查点是if()VALID 和if()INVALID 的经典检查点。而且,当然,我得到一个告诉我这一切都再次无效的消息。

希望我提供的这些详细信息能让某人的灯泡闪闪发光!至于我,我还是傻眼了。

提前致谢!


非常感谢你们的回复!

我还没有尝试过第二个,虽然它听起来很明智。听起来这可能是我从 PayPal 获得的原始代码的问题。如果我有时间尝试一下,看看代码是否适用,我会在这里发布我的反馈。希望有人会发现这一切都很有用。

经过一个星期的头撞墙和一点时间来冷静大脑中的问题后,我终于在几天前找到了另一种解决问题的方法,该方法与第二种方法非常相似六氰化物反应的一部分。我在下面为任何关注此字符串的人发布它。但是,我必须说,PayPal 代码有很多错误。至少我收到的那个。从那以后,我遇到了其他几个必须通过变通方法解决的问题。最糟糕的是,PayPal 根本不支持。我什至打了三次:第一次,那个人挂了我;然后,他们告诉我这可能是病毒问题(当他们真的不知道发生了什么时的典型反应)。

无论如何,我希望我能评价你的两个回答,但我需要超过 +15 分,所以我会在这里口头表扬他们。我按原样尝试了 Hexacynide 的响应代码,但它对我不起作用,所以我无法将其标记为已检查。如果我将来有时间尝试另一个,并且它有效,我会将其标记为正确。

在那之前,这是我使用 CURL 进行的代码更新。

    $ch = curl_init('https://www.paypal.com/pe/cgi-bin/webscr');
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));

    if( !($res = curl_exec($ch)) ) {
        // error_log("Got " . curl_error($ch) . " when processing IPN data");
        curl_close($ch);
        exit;
    }
    curl_close($ch);

注意:这里它针对的是真实的东西,因为它现在已经启动并运行,但是,使用它也可以sandbox.工作。

4

3 回答 3

4

我是 Stackoverflow 的新手,所以我没有意识到可以回答自己的问题。无论如何,我已经在原帖结尾处回答了它,并在上周对其进行了编辑。现在我将它包含在这里,以便任何遇到此类问题的人都可以参考它并意识到这是我能够解决问题的方式。

我尝试了其他贡献者在这里给出的第一个解决方案,但不幸的是它对我不起作用。一旦我已经能够以另一种方式解决它,第二个解决方案就到了,所以我没有尝试过。也许我会在未来的某个时候得到它。但是,如果有人尝试过,请在此处留下您的评论,以便其他人从智慧中受益。

这是我的解决方案:

经过一个星期的头撞墙和一点时间来冷静大脑中的问题后,我终于在几天前找到了另一种解决问题的方法,该方法与第二种方法非常相似六氰化物反应的一部分。我在下面为任何关注此字符串的人发布它。但是,我必须说,PayPal 代码有很多错误。至少我收到的那个。从那以后,我遇到了其他几个必须通过变通方法解决的问题。最糟糕的是,PayPal 根本不支持。我什至打了三次:第一次,那个人挂了我;然后,他们告诉我这可能是病毒问题(当他们真的不知道发生了什么时的典型反应)。

无论如何,我希望我能评价你的两个回答,但我需要超过 +15 分,所以我会在这里口头表扬他们。我按原样尝试了 Hexacynide 的响应代码,但它对我不起作用,所以我无法将其标记为已检查。如果我将来有时间尝试另一个,并且它有效,我会将其标记为正确。

在那之前,这是我使用 CURL 进行的代码更新。

    $ch = curl_init('https://www.paypal.com/pe/cgi-bin/webscr');
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));

    if( !($res = curl_exec($ch)) ) {
        // error_log("Got " . curl_error($ch) . " when processing IPN data");
        curl_close($ch);
        exit;
    }
    curl_close($ch);

注意:这里它针对的是真实的东西,因为它现在已经启动并运行,但是,使用它也可以sandbox.工作。

于 2013-03-09T03:25:07.087 回答
3

尝试改变这个:

// post back to PayPal system to validate
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('www.sandbox.paypal.com', 80, $errno, $errstr, 30);

对此:

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

从本质上讲,PayPal 将停止支持 HTTP 1.0。我相信它已经在 Sandbox 上停产了,但它仍然在现场站点上得到支持(但不会持续太久)。这篇文章有更多关于它的信息:https ://www.paypal-notify.com/eventnotification/event_details?eventId=2891

此外,您应该回发到启用 SSL 的主机。我想说 PayPal 将拒绝验证 HTTP URL 上的 IPN(并且只是重定向到启用 SSL 的服务器上的 PayPal 主页),但我对此不是 100% 确定的。

最后,回答您的问题——IPN 是一个异步过程,直到付款完成后才会开始。因此,如果您因任何原因没有收到 IPN,则付款已经完成,不会因为您没有收到 IPN 而被撤销。如果您想要在付款之前肯定会回复您的网站的东西,我建议您查看 Express Checkout。

于 2013-02-11T16:01:43.750 回答
1

我刚刚经历过这个。您必须将命令附加到响应而不是添加它。完成此操作后,您应该会收到来自贝宝的令人垂涎的“已验证”回复。为了您的方便,我发布了对我有用的代码。兄弟,我一直在你所在的地方,我想我会真正做出回应,而不是关闭浏览器并上床睡觉(我也为此度过了漫长的一天!)。无论如何,没有进一步的告别,这里是:

function verifyPayment($request)
{
    if($request->is('post') && !empty($request->data))
    {
        //build response string
        $response = '';
        foreach($request->data as $field => $value)
        {
            //build response string
            $response .= $field . '=' . urlencode(stripslashes($value)) . '&';
        }
        if(empty($id))
        {
            return false; //invalid transaction
        }
        //append notify validate command
        $response .= "cmd=_notify-validate"; 
        //respond to paypal - open connection
        $parsedUrl = parse_url('https://www.sandbox.paypal.com/cgi-bin/webscr');
        $sock = fsockopen('ssl://' . $parsedUrl['host'], "443", $errorNumber, $error, 30);
        if(!$sock)
        {
            return false; //could not open connection - must be able to verify
        }
        //post data back to paypal
        fputs($sock, "POST $parsedUrl[path] HTTP/1.1\r\n");
        fputs($sock, "Host: $parsedUrl[host]\r\n");
        fputs($sock, "Content-type: application/x-www-form-urlencoded\r\n");
        fputs($sock, "Content-length: " . strlen($response) . "\r\n");
        fputs($sock, "Connection: close\r\n\r\n");
        fputs($sock, $response . "\r\n\r\n");
        //loop through response and append
        $ipnResponse = '';
        while(!feof($sock))
        {
            $ipnResponse .= fgets($sock, 1024);
        }
        //close connection
        fclose($sock);
        if(!eregi("VERIFIED", $ipnResponse))
        {
            return false; //paypal reports invalid transaction
        }
        //if we made it here, transaction is valid
        return true;
    }
}

我真诚地希望这可以帮助您和其他任何人处理贝宝的挫败感!

干杯! 杰伊·古德

于 2013-12-07T04:54:35.903 回答