PayPal IPN和fsockopen

时间:2016-01-23 01:24:04

标签: php paypal paypal-ipn fsockopen

我无法使用cURL,我的网站主机上安装的无法更改的版本不支持TLS。

我正在尝试使用fsockopen来查看我是否能够使用IPN。

它只是挂起,浏览器抛出连接超时。

PHP 7,启用open_ssl

<?php
    header('HTTP/1.1 200 OK'); 

    $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'];

    $req = 'cmd=_notify-validate';               // Add 'cmd=_notify-validate' to beginning of the acknowledgement
    foreach ($_POST as $key => $value) {         // Loop through the notification NV pairs
        $value = urlencode(stripslashes($value));  // Encode these values
        $req  .= "&$key=$value";                   // Add the NV pairs to the acknowledgement
    }

    // Set up the acknowledgement request headers
    $header  = "POST /cgi-bin/webscr HTTP/1.1\r\n";                    // HTTP POST request
    $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
    $header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

    // Open a socket for the acknowledgement request
     $fp = fsockopen('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);

    // Send the HTTP POST request back to PayPal for validation
    fputs($fp, $header . $req);

    while (!feof($fp)) {                     // While not EOF

    $res = trim(fgets ($fp, 1024));

    if (strcmp ($res, "VERIFIED") == 0) {  // Response contains VERIFIED - process notification

      file_put_contents('./log_'.date("j.n.Y").'.txt', 'VERIFIED', FILE_APPEND);
    } 
    else if (strcmp ($res, "INVALID") == 0) { Response contains INVALID - reject notification
        file_put_contents('./log_'.date("j.n.Y").'.txt', 'INVALID', FILE_APPEND);
    }
  }
  //close
  fclose($fp);
?>

更新

因此,我的当前代码似乎存在问题。我使用以下内容来查看是否可以与PayPal通信。

<?php

$site = "sandbox.paypal.com";//works
$port = 443;

$fp = fsockopen($site, $port, $errno, $errstr, 30);

if(!$fp){
  echo "<b>The port is NOT open!</b>";
}else{
  echo "<b>The port is open!</b>";
  fclose($fp);
}

?>

结果为The port is open!

更新2

好的我现在正在使用以下代码从IPN模拟器获得响应。我遇到的其他问题是我没有使用我的听众的FQDN并且离开了http://。

所以现在下一个问题是$res = trim($res);总是空白但我的帖子变量不是。这是因为它是沙盒吗?

<?php 
    $debug            = 1;
    $sandbox          = 1;

    header('HTTP/1.1 200 OK'); 

    $item_name        = $_POST['item_name'];
    $item_number      = $_POST['item_number'];
    $payment_status   = $_POST['payment_status'];   
    if ($_POST['mc_gross'] != null) {
        $payment_amount   = $_POST['mc_gross'];
    } else {
        $payment_amount   = $_POST['mc_gross1'];
    }
    $payment_currency = $_POST['mc_currency'];
    $txn_id           = $_POST['txn_id'];
    $receiver_email   = $_POST['receiver_email'];
    $payer_email      = $_POST['payer_email'];
    $payment_date     = $_POST['payment_date'];
    $first_name       = $_POST['first_name'];
    $last_name        = $_POST['last_name'];
    $item_name        = $_POST['item_name'];

    $sandbox_url      = "sandbox.paypal.com";
    $prod_url         = "paypal.com";
    $verfiy_email     = "you email address the payment should be made to";

    if ($sandbox) {
        $url = $sandbox_url;
    } else {
        $url = $prod_url;
    }

    if ($debug) {
        error_log(date('[Y-m-d H:i e] '). "IPN URL: " . $url . PHP_EOL, 3, LOG_FILE);
    }

    $req = 'cmd=_notify-validate';               // Add 'cmd=_notify-validate' to beginning of the acknowledgement
    foreach ($_POST as $key => $value) {         // Loop through the notification NV pairs
        $value = urlencode(stripslashes($value));  // Encode these values
        $req  .= "&$key=$value";                   // Add the NV pairs to the acknowledgement

        if ($debug) {
            error_log(date('[Y-m-d H:i e] '). "POST Data: " . $key . " - " . $value . PHP_EOL, 3, LOG_FILE);
        }
    }

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

    //error connecting to paypal
    if (!$fp) {
        error_log(date('[Y-m-d H:i e] '). "Can't connect to PayPal to validate IPN message: " . $errno . " - " . $errstr . PHP_EOL, 3, LOG_FILE);
    }

    //successful connection    
    if ($fp) {
        fputs ($fp, $header . $req);

        while (!feof($fp)) {
            $res = fgets ($fp, 1024);
            $res = trim($res); //NEW & IMPORTANT

            if ($debug) {
                error_log(date('[Y-m-d H:i e] '). "DEBUG: Validation - " . $res . PHP_EOL, 3, LOG_FILE);
                error_log(date('[Y-m-d H:i e] '). "DEBUG: Payment Status - " . $payment_status . PHP_EOL, 3, LOG_FILE);
                error_log(date('[Y-m-d H:i e] '). "DEBUG: Receiver Email - " . $receiver_email . PHP_EOL, 3, LOG_FILE);
                error_log(date('[Y-m-d H:i e] '). "DEBUG: Verify Email - " . $verfiy_email . PHP_EOL, 3, LOG_FILE);
            }

            //I don't see this
            if (strcmp($res, "VERIFIED") == 0) {
                //insert order into database    
                if ($debug) {
                    error_log(date('[Y-m-d H:i e] '). "Response Message: " . "VERIFIED" . PHP_EOL, 3, LOG_FILE);
                }
            }

            //I don't see this
            if (strcmp ($res, "INVALID") == 0) {
                //insert into DB in a table for bad payments for you to process later
                if ($debug) {
                    error_log(date('[Y-m-d H:i e] '). "Response Message: " . "INVALID" . PHP_EOL, 3, LOG_FILE);
                }
            }

            if (strcasecmp ($payment_status, "Completed") == 0 && strcasecmp($receiver_email, $verfiy_email) == 0) {
                if ($debug) {
                    error_log(date('[Y-m-d H:i e] '). "Response Message: " . "Payment VERIFIED" . PHP_EOL, 3, LOG_FILE);
                }
            } else {
                if ($debug) {
                    error_log(date('[Y-m-d H:i e] '). "Response Message: " . "Payment INVALID" . PHP_EOL, 3, LOG_FILE);
                }
            }
        }

        fclose($fp);
    }
?>

3 个答案:

答案 0 :(得分:0)

{ "size": 0, "query": { "bool": { "must": [ { "bool": { "should": [ { "bool": { "must": [ { "term": { "partnersites": "16" } }, { "match_phrase_prefix": { "name": "mancheste" } } ] } }, { "bool": { "must": [ { "term": { "partnersites": "16" } }, { "match_phrase_prefix": { "venueName": "mancheste" } } ] } }, { "bool": { "must": [ { "term": { "partnersites": "16" } }, { "match_phrase_prefix": { "venueTown": "mancheste" } } ] } } ] } } ] } }, "aggs": { "distinct_names": { "terms": { "field": "groupedName.keyword", "size": 30 }, "aggs": { "top_tag_hits": { "top_hits": { "size": 1, "_source": [ "groupedName", "groupedDisplayName", "groupedUrl", "eventCode", "venueName", "venueTown", "venueId", "media" ] } } } } } } 循环访问请求响应,有时读取1024字节,在最后一次迭代时只留空。

如果您尝试通过循环在某处记录$res变量,您只需逐行找到响应,例如

$res

这不是解决而是......只是一个想法。 :)

答案 1 :(得分:0)

感谢您的发帖!我有一个类似的问题,IPN被发送,我的服务器使用fsocket验证它,执行代码写入数据库,但PayPal仍然报告了一个&#39;交付状态&#39; &#39;失败&#39;重试几次后,在我的数据库中导致重复。在查看了您的代码后,我发现我正在处理的教程遗漏了这一行,导致PayPal的请求超时而不是显示200:

    $header .= "Connection: close\r\n";

答案 2 :(得分:0)

我遇到了同样的问题,沙箱返回一个空结果。我的代码类似于Tsukasa提供的Update 2.

我不得不将sandbox.paypal.com更改为ipnbp.sandbox.paypal.com,并在其前面加上ssl。 fsocket调用看起来像:

wget --no check certificate --user=my username --password=my password URL