curl_setopt cacert.pem for paypal

Zbarcea Christian picture Zbarcea Christian · Mar 12, 2013 · Viewed 12.1k times · Source

I'm trying to set up a callback handler for IPN (paypal) verification. I know what curl does, but I don't know what 'cacert.pem' is (certificate...?).

this is where the callback.php file fails (exists):

curl_setopt($ch, CURLOPT_CAINFO, 'cacert.pem');
if( !($res = curl_exec($ch)) ) {
    echo ("Got " . curl_error($ch) . " when processing IPN data");
    curl_close($ch);
    exit;
}
curl_close($ch);

With the following error message:

Got error setting certificate verify locations: CAfile: cacert.pem CApath: none when processing IPN data

So I downloaded cacert.pem and copied to the directory where the callback.php file is.

This is a comment before the code above:

// In wamp like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path 
// of the certificate as shown below.

I'm using XAMPP, this would be the problem?

And finally this is the whole php file directly from developer page: https://www.x.com/developers/PayPal/documentation-tools/code-sample/216623

<?php

// STEP 1: Read POST data

// reading posted data from directly from $_POST causes serialization 
// issues with array data in POST
// reading raw POST data from input stream instead. 
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
  $keyval = explode ('=', $keyval);
  if (count($keyval) == 2)
     $myPost[$keyval[0]] = urldecode($keyval[1]);
}
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
   $get_magic_quotes_exists = true;
} 
foreach ($myPost as $key => $value) {        
   if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) { 
        $value = urlencode(stripslashes($value)); 
   } else {
        $value = urlencode($value);
   }
   $req .= "&$key=$value";
}


// STEP 2: Post IPN data back to paypal to validate

$ch = curl_init('https://www.sandbox.paypal.com/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'));

// In wamp like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path 
// of the certificate as shown below.
curl_setopt($ch, CURLOPT_CAINFO, 'cacert.pem');
if( !($res = curl_exec($ch)) ) {
    echo ("Got " . curl_error($ch) . " when processing IPN data");
    curl_close($ch);
    exit;
}
curl_close($ch);

// STEP 3: Inspect IPN validation result and act accordingly

if (strcmp ($res, "VERIFIED") == 0) {
    // check whether the payment_status is Completed
    // check that txn_id has not been previously processed
    // check that receiver_email is your Primary PayPal email
    // check that payment_amount/payment_currency are correct
    // process payment

    // assign posted variables to local variables
    $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'];

    $string = "------------------------\r\n";
    $string .= "item_name: ".$item_name."\r\n";
    $string .= "item_number: ".$item_number."\r\n";
    $string .= "payment_status: ".$payment_status."\r\n";
    $string .= "payment_amount: ".$payment_amount."\r\n";
    $string .= "payment_currency: ".$payment_currency."\r\n";
    $string .= "txn_id: ".$txn_id."\r\n";
    $string .= "receiver_email: ".$receiver_email."\r\n";
    $string .= "payer_email: ".$payer_email."\r\n";

    $fp = fopen('test.log', 'w');
    fwrite($fp, $string."\r\n");
    fclose($fp);

} else if (strcmp ($res, "INVALID") == 0) {
    // log for manual investigation
}
?>

Answer

Chris L picture Chris L · Mar 12, 2013

As per the comment you need to set the (full) directory path, if the pem file is in the same directory as the script then this should work:

curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');

For an explanation of what the cacert.pem file is, check this accepted answer.