PayPal IPN and fsockopen

烈酒焚心 提交于 2020-01-06 19:56:55

问题


Well I can't use cURL, the version installed on my web host that can't be changed doesn't support TLS.

I'm trying to use fsockopen now to see if i'll be able to use IPN.

It just hangs and browser throws connection timeout.

PHP 7, open_ssl is enabled

<?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);
?>

UPDATE

So it appears to be an issue with my current code. I used the following to see if I could talk to 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 result is The port is open!

UPDATE 2

Ok I'm now getting the response from the IPN Simulator using the below code. The other issues I was having was I failed to use the FQDN of my listener and left off http://.

So now the next problem is $res = trim($res); is always blank but my post variables aren't. Is this because it's a sandbox?

<?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);
    }
?>

回答1:


$res is cycling through the request response, reading it 1024bytes at times, leaving it just empty on its last iteration.

If you try to log somewhere the $res variable through the loop, you'll just find the response line-by-line, eg.

HTTP/1.0 302 Found 
Location: https://www.sandbox.paypal.com
Server: BigIP
Connection: close 

It's not solving but.. just an idea. :)




回答2:


Thank you for posting! I was having a similar issue where the IPN was sent, my server validated it using fsocket, code was executed to write to database, but PayPal still reported a 'delivery status' of 'failed' after retrying several times causing duplicates in my database. After reviewing your code I found that the tutorial I've been working off of left out this line causing the request from PayPal to timeout instead of show 200:

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



回答3:


I encountered the same issue, where the sandbox was returning an empty result. My code was similar to the Update 2 provided by Tsukasa.

I had to change sandbox.paypal.com to ipnbp.sandbox.paypal.com, and prefix it with ssl. The fsocket call looks like:

$fp = fsockopen ('ssl://ipnbp.sandbox.paypal.com', 443, $errno, $errstr, 30);


来源:https://stackoverflow.com/questions/34958560/paypal-ipn-and-fsockopen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!