3

I'm just testing the Paypal IPN here. I've got it set up with Sandbox. I'm sending it fake IPN requests, and it's receiving the IPN. Then, I'm getting it to return the information for verification, and I'm writing the response to a text file so I can check it out on my own. The IPN is firing fine, and the response is getting written to the text file.

There's just one problem... The response is blank.

The response is supposed to be received as "VERIFIED" or "INVALID", and these are the only 2 possible responses... so what's going on =S. Any help is greatly appreciated.

The entire code is posted below:

$ipn_post_data = $_POST;

$response = "";

    // Choose url
    $url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';

    // Set up request to PayPal
    $request = curl_init();
    curl_setopt_array($request, array
    (
        CURLOPT_URL => $url,
        CURLOPT_POST => TRUE,
        CURLOPT_POSTFIELDS => http_build_query(array('cmd' => '_notify-validate') + $ipn_post_data),
        CURLOPT_RETURNTRANSFER => TRUE,
        CURLOPT_HEADER => FALSE,
        CURLOPT_SSL_VERIFYPEER => TRUE,
        CURLOPT_CAINFO => 'cacert.pem',
    ));

    // Execute request and get response and status code
    $response = curl_exec($request);
    $status   = curl_getinfo($request, CURLINFO_HTTP_CODE);

    // Close connection
    curl_close($request);


$fh = fopen( "ipntest.txt", 'a+' );
$date = date( "Y-M-j H:i" );
fwrite( $fh, $date . " Response: " . $response . "\n" );
fclose( $fh );

if($status == 200 && $response == 'VERIFIED')
{
    // All good! Proceed...
}
else
{
    // Not good. Ignore, or log for investigation...
}

Text file output:

2012-Nov-26 23:24 Response: 
2012-Nov-26 23:25 Response: 

I had been using this code previously, I've been trying to get it to work for a week, so it's not just a temporary failure or something...

Cheers guys.

connorbode
  • 3,015
  • 1
  • 28
  • 31
  • 1
    Give this library a try: https://github.com/Quixotix/PHP-PayPal-IPN I had the same problem at some point of my dev... i quit troubleshooting and start using that fantastic library. – eldblz Nov 27 '12 at 07:11
  • 1
    This may well just be an https thing. Have you determined the return value of curl_exec()? Is it false perhaps? – Ja͢ck Nov 27 '12 at 12:57
  • Bigups for that eldblz, that made my life so much easier. The issue was that I didn't have a CA file. See the answer I posted below. – connorbode Nov 28 '12 at 14:02

3 Answers3

3

So just for future reference, for people with this same problem:

The issue here was not having a CA file.

I'm unsure what exactly a CA file does but I know it has something to do with Paypal's SSL certificate and establishing an SSL connection. When I started looking at cURL's errors, I saw the following:

[27-Nov-2012 21:46:11 UTC] cURL error: [77] error setting certificate verify locations:
  CAfile: /etc/ssl/certs/api_cert_chain.crt
  CApath: /etc/ssl/certs

The quick solution that I found was to download the IpnListener.php class. (This was recommended by eldblz. It made dealing with IPN way easier AND it provided a solution to my not having a CAFile. If you download the entire IpnListener.php package, it includes a folder called cert which includes the api_cert_chain.crt that you need, and already has it configured for use.

Community
  • 1
  • 1
connorbode
  • 3,015
  • 1
  • 28
  • 31
  • 2
    When you establish an SSL connection, the server will return its own certificate (which is used to secure the connection) together with a chain of intermediate certificates leading up to the authority; the latter is then looked up in a certificate authority bundle file (the CA file) and verified to make sure you're talking to the right guy. Hope that helps :) – Ja͢ck Nov 29 '12 at 09:12
  • 1
    The actual issue was that you didn't check the result of `curl_exec()`, which in this case was `false`; then with `curl_error($ch)` you can check what the error was. – Ja͢ck Nov 29 '12 at 09:13
0

I've always used the following and it works nicely...

// Validate with curl
$curl_result=$curl_err='';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,'https://'.$ppHost.'/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($req)));
curl_setopt($ch, CURLOPT_HEADER , 1);   
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $ssl);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);

$curl_result = curl_exec($ch);
$curl_err = curl_error($ch);
curl_close($ch);

//are we verified? If so, let's process the IPN
if (strpos($curl_result, "VERIFIED")!==false) 
    $valid = true;
else
    $valid = false;

You would just need to make sure $ppHost in this sample was correct depending on whether the transaction came from the sandbox or the live servers, and then of course fill in $req and $ssl accordingly.

Drew Angell
  • 25,968
  • 5
  • 32
  • 51
0
class Paypal_IPN
{
    /** @var string $_url The paypal url to go to through cURL
    private $_url;

    /**
    * @param string $mode 'live' or 'sandbox' 
    */
    public function __construct($mode = 'live')
    {
        if ($mode == 'live')
        $this->_url = 'https://www.paypal.com/cgi-bin/webscr';

        else
        $this->_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
    }

    public function run()
    {
        $postFields = 'cmd=_notify-validate';

        foreach($_POST as $key => $value)
        {
            $postFields .= "&$key=".urlencode($value);
        }

        $ch = curl_init();

        curl_setopt_array($ch, array(
            CURLOPT_URL => $this->_url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $postFields
        ));

        $result = curl_exec($ch);
        curl_close($ch);

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

        echo $result;
    }
}

call this in another php file:

<?php
require 'Paypal_IPN.php';
$paypal= new Paypal_IPN('sandbox');
$paypal->run();

?>
rOcKiNg RhO
  • 631
  • 1
  • 6
  • 16