Securing PayPal Checkout

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 16

Protecting Payment Buttons by Using

Encrypted Website Payments


Securing PayPal Checkout
Manish Ranjan
Table of contents
1. Generating Your Private Key Using OpenSSL..........................................................................................2
2. Generating Your Public Certificate Using OpenSSL..................................................................................2
3. Uploading Your Public Certificate to Your PayPal Account......................................................................2
4. Downloading the PayPal Public Certificate From the PayPal Website.....................................................3
5. Implement PayPal Secure button in a project.........................................................................................4

Securing PayPal Checkout button Page 1 of 17


1. Generating Your Private Key Using OpenSSL

Using the openssl program, enter the following command to generate your private key. The command
generates a 1024-bit RSA private key that is stored in the file my-prvkey.pem:

openssl genrsa -out my-prvkey.pem 1024

2. Generating Your Public Certificate Using OpenSSL

The public certificate must be in PEM format. To generate your certificate, enter the following openssl
command, which generates a public certificate in the file my-pubcert.pem:

openssl req -new -key my-prvkey.pem -x509 -days 365 -out my-pubcert.pem

3. Uploading Your Public Certificate to Your PayPal Account

To upload your public certificate to your PayPal account:

1. Log in to your PayPal Business or Premier account.

2. Click the Profile subtab.

3. In the Selling Preferences column, click the Encrypted Payment Settings link.

The Website Payment Certificates page appears.

4. Scroll down the page to the Your Public Certificates section, and click the Add button.

The Add Certificate page appears.

5. Click the Browse button, and select the public certificate that you want to upload to PayPal from
your local computer.

Note: The file you upload must be in PEM format.

6. Click the Add button.

After your public certificate is uploaded successfully, it appears in the Your Public Certificates
section of the Website Payment Certificates page.

Securing PayPal Checkout button Page 2 of 17


7. Store the certificate ID that PayPal assigned to your public certificate in a secure place.

You need the certificate ID that PayPal assigned to encrypt your payment buttons by using the
Encrypted Website Payments software provided by PayPal.

4. Downloading the PayPal Public Certificate From the PayPal Website

To download the PayPal public certificate:

1. Log in to your Business or Premier PayPal account.

2. Click the Profile subtab.

3. In the Seller Preferences column, click the Encrypted Payment Settings link.

4. Scroll down the page to the PayPal Public Certificate section.

5. Click the Download button, and save the file in a secure location on your local computer.

Securing PayPal Checkout button Page 3 of 17


5. Implement PayPal Secure button in a project

require_once(“./PayPalEWP.class.php");

/** Create a new instance of the class **/


$paypal = new PayPalEWP();

/** This will contain the encrypted button text **/


$encryptedButton = "";

/** For a list of thrown exceptions, refer to the bottom of PayPalEWP.class.php **/
try {
if(!isset($discountAmt)){
$discountAmt='0.00';
}
/** set standard PayPal variables in an array **/
$fields = array("cmd" => "_xclick",
"business" => $paypal_account,
"item_name" => $item_name,
"amount" => $totalcost,
"discount_amount" => $discountAmt,
"on0" => "Transaction ID#",
"on1" => "User ID#",
"os0" => $yourorderid,
"os1" => $loggedinuserid,
"no_shipping" => "1",
"return" => HTTP_PATH."/ComfirmPayment.php",
"cancel_return" => HTTP_PATH."/Cancel.php",
"notify_url" => HTTP_PATH."/Notify.php",
"no_note" => "1",
"currency_code" => "USD",
"bn" => "PP-BuyNowBF"
);

/** Temporary directory for file storage. Make sure it's writable **/
$paypal->setTempDirectory("/tmp");

/** The user certificate and private key you generated **/
$paypal->setUserCertificate("site-public.pem", "site.pem");

/** The certificate PayPal gave you **/


$paypal->setPaypalCertificate("paypal_cert.pem");

/** The ID of the certificate PayPal gave you **/


$paypal->setPaypalCertificateID("P75YBBV2DJQJS");

/** Generate the encrypted button **/

Securing PayPal Checkout button Page 4 of 17


$encryptedButton = $paypal->encryptButton($fields);
?>
<form name="_xclick" id="_xclick" action="https://www.paypal.com/cgi-bin/webscr" method="POST">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="image" src="/Images/btn_xpressCheckout.gif" border="0" name="submit">
<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----<?php echo $encryptedButton; ?
>-----END PKCS7-----">
</form>

PayPalEWP.class.php

<?php

/**
* Class for creating Paypal Encrypted Website Payment buttons
*
* Uses given user certificate, user private key, PayPal
* certificate, and PayPal certificate ID to create form
* content from the given array and then encrypt using
* the above details according to the PayPal EWP standard.
*
* @author Joshua Gilman
* @version 1.0.0
* @package PayPalLib
*
*/
class PayPalEWP
{
private $userCertificate;
private $userCertificateFile;

private $userKey;
private $userKeyFile;

private $paypalCertificate;
private $paypalCertificateFile;

private $paypalCertificateID;

private $tempDirectory;

/**
* Takes the given form fields and encrypts
* them according to the PayPal EWP standard
* returning the encrypted button code.
*

Securing PayPal Checkout button Page 5 of 17


* @param Array $fields
* @return String
*/
public function encryptButton($fields)
{
/** Make sure we have a user certificate **/
if ($this->userCertificate == NULL)
{
throw new emptyFieldException("userCertificate");
}

/** Make sure we have a PayPal certificate **/


if ($this->paypalCertificate == NULL)
{
throw new emptyFieldException("paypalCertificate");
}

/** Make sure we have a PayPal certificate ID **/


if ($this->paypalCertificateID == NULL)
{
throw new emptyFieldException("paypalCertificateID");
}

/** Define variables to be used later **/


$plainText = "";
$signedText = array();
$encText = "";

/** Start off the form data with the PayPal certificate ID **/
$plainText .= "cert_id=" . $this->paypalCertificateID;

/** Create the form data by separating each value set by a new line character **/
foreach($fields as $key => $value)
{
$plainText .= "\n{$key}={$value}";
}

/** Create a temporary file to begin storing our data as we process it **/
$dataFile = tempnam($this->tempDirectory, "data");

/** First create a file for storing the plain text value of the form data **/
$fh = fopen($dataFile . "_plain.txt", 'wb');
fwrite($fh, $plainText);
fclose($fh);

/** Open a handle for outputting the signed data **/


$fh = fopen($dataFile . "_signed.txt", "w+");

Securing PayPal Checkout button Page 6 of 17


/** Sign the plain text file using the given user certificate and user key **/
if (!openssl_pkcs7_sign($dataFile . "_plain.txt", $dataFile . "_signed.txt", $this-
>userCertificate, $this->userKey, array(), PKCS7_BINARY))
{
throw new signFailedException($dataFile . "_plain.txt", $this->userCertificateFile,
$this->userKeyFile);
}

/** Close our previously opened handle **/


fclose($fh);

/** Parse the signed file between the header and content **/
$signedText = explode("\n\n", file_get_contents($dataFile . "_signed.txt"));

/** Save only the content but base64 decode it first **/
$fh = fopen($dataFile . "_signed.txt", 'wb');
fwrite($fh, base64_decode($signedText[1]));
fclose($fh);

/** Now encrypt the signed file we just wrote to using the PayPal certificate **/
if (!openssl_pkcs7_encrypt($dataFile . "_signed.txt", $dataFile . "_enc.txt", $this-
>paypalCertificate, array(), PKCS7_BINARY))
{
throw new encryptFailedException($dataFile . "_signed.txt", $this-
>paypalCertificateFile);
}

/** Parse the encrypted file between header and content and grab the content **/
$encryptedData = explode("\n\n", file_get_contents($dataFile . "_enc.txt"));
$encText = $encryptedData[1];

/** Delete all of our temporary files **/


@unlink($dataFile);
@unlink($dataFile . "_plain.txt");
@unlink($dataFile . "_signed.txt");
@unlink($dataFile . "_enc.txt");

/** Return the now encrypted form content **/


return $encText;
}

/**
* Sets the user certificate to be used with encryption.
*
* @param String $userCertificateFile
* @param String $userKeyFile
* @return Boolean
*/

Securing PayPal Checkout button Page 7 of 17


public function setUserCertificate($userCertificateFile, $userKeyFile)
{
/** Make sure the user certificate file is valid **/
if (!is_readable($userCertificateFile))
{
throw new invalUserCertException($userCertificateFile);
}

/** Make sure the user key file is valid **/


if (!is_readable($userKeyFile))
{
throw new invalKeyException($userKeyFile);
}

/** Set the appropriate values **/


$this->userCertificateFile = $userCertificateFile;
$this->userKeyFile = $userKeyFile;

/** Load the resource handles for both the user certificate and key **/
$cert = openssl_x509_read(file_get_contents($this->userCertificateFile));
$key = openssl_get_privatekey(file_get_contents($this->userKeyFile));

/** Make sure the certificate is valid **/


if ($cert === FALSE)
{
throw new invalUserCertException($this->userCertificateFile);
}

/** Make sure the key is valid **/


if ($key === FALSE)
{
throw new invalKeyException($this->userKeyFile);
}

/** Make sure this key and certificate belong together **/
if (!openssl_x509_check_private_key($cert, $key))
{
throw new invalCertKey($this->userCertificateFile, $this->userKeyFile);
}

/** Assign the appropriate values **/


$this->userCertificate = $cert;
$this->userKey = $key;

return TRUE;
}

/**

Securing PayPal Checkout button Page 8 of 17


* Sets the PayPal certificate to be used with encryption.
*
* @param String $paypalCertificateFile
* @return Boolean
*/
public function setPaypalCertificate($paypalCertificateFile)
{
/** Make sure the certificate file is valid **/
if (!is_readable($paypalCertificateFile))
{
throw new invalPaypalCertException($paypalCertificateFile);
}

/** Set the proper values **/


$this->paypalCertificateFile = $paypalCertificateFile;

/** Grab the resource of the PayPal certificate **/


$cert = openssl_x509_read(file_get_contents($this->paypalCertificateFile));

/** Make sure the certificate is valid **/


if ($cert === FALSE)
{
throw new invalPaypalCertException($this->paypalCertificateFile);
}

/** Assign the appropriate values **/


$this->paypalCertificate = $cert;

return TRUE;
}

/**
* Sets the PayPal certificate ID to be used with encryption.
*
* @param String $paypalCertificateID
*/
public function setPaypalCertificateID($paypalCertificateID)
{
$this->paypalCertificateID = $paypalCertificateID;
}

/**
* Sets the temporary directory the encryption process will use.
*
* @param String $tempDirectory
* @return Boolean
*/
public function setTempDirectory($tempDirectory)

Securing PayPal Checkout button Page 9 of 17


{
/** Make sure the temporary directory is valid **/
if (!is_dir($tempDirectory) || !is_writable($tempDirectory))
{
throw new invalTempDirectory($tempDirectory);
}

/** Assign the appropriate values **/


$this->tempDirectory = $tempDirectory;

return TRUE;
}
}

/** Below are defined exceptions used by the PayPalEWP class **/

/**
* Thrown when an invalid user certificate is used.
*
*/
class invalUserCertException extends Exception
{
private $certFile;

public function __construct($certFile)


{
$this->certFile = $certFile;
}

public function getCertFile()


{
return $this->certFile;
}

public function __toString()


{
return "Invalid User Certificate File: \"{$this->certFile}\"";
}
}

/**
* Thrown when an invalid PayPal certificate is given
*
*/
class invalPaypalCertException extends Exception
{
private $paypalCertFile;

Securing PayPal Checkout button Page 10 of 17


public function __construct($paypalCertFile)
{
$this->paypalCertFile = $paypalCertFile;
}

public function getPaypalCertFile()


{
return $this->paypalCertFile;
}

public function __toString()


{
return "Invalid PayPal Certificate File: \"{$this->paypalCertFile}\"";
}
}

/**
* Thrown when an invalid user key is given
*
*/
class invalKeyException extends Exception
{
private $keyFile;

public function __construct($keyFile)


{
$this->keyFile = $keyFile;
}

public function getKeyFile()


{
return $this->keyFile;
}

public function __toString()


{
return "Invalid User Key File: \"{$this->keyFile}\"";
}
}

/**
* Thrown when an invalid user certificate is given
*
*/
class invalCertKey extends Exception
{
private $certFile;

Securing PayPal Checkout button Page 11 of 17


private $keyFile;

public function __construct($certFile, $keyFile)


{
$this->certFile = $certFile;
$this->keyFile = $keyFile;
}

public function getCertFile()


{
return $this->certFile;
}

public function getKeyFile()


{
return $this->keyFile;
}

public function __toString()


{
return "Key file: \"{$this->keyFile}\" does not belong to Certificate file: \"{$this-
>certFile}\"";
}
}

/**
* Thrown when an invalid temporary directory is given
*
*/
class invalTempDirectory extends Exception
{
private $tmpDir;

public function __construct($tmpDir)


{
$this->tmpDir = $tmpDir;
}

public function getTmpDir()


{
return $this->tmpDir;
}

public function __toString()


{
return "Invalid temporary directory: \"{$this->tmpDir}\"";
}
}

Securing PayPal Checkout button Page 12 of 17


/**
* Thrown when one of the required fields used in PayPalEWP:EncryptButton is NULL
*
*/
class emptyFieldException extends Exception
{
private $field;

public function __construct($field)


{
$this->field = $field;
}

public function getField()


{
return $this->field;
}

public function __toString()


{
return "The required field '{$this->field}' is empty";
}
}

/**
* Thrown when the signing of a file using a user certificate and user key failed
*
*/
class signFailedException extends Exception
{
private $contentFile;
private $certFile;
private $keyFile;

public function __construct($contentFile, $certFile, $keyFile)


{
$this->contentFile = $contentFile;
$this->certFile = $certFile;
$this->keyFile = $keyFile;
}

public function getContentFile()


{
return $this->contentFile;
}

public function getCertFile()

Securing PayPal Checkout button Page 13 of 17


{
return $this->certFile;
}

public function getKeyFile()


{
return $this->keyFile;
}

public function __toString()


{
return "Failed to sign file '{$this->contentFile}' with user certificate '{$this->certFile}'
and user key '{$this->keyFile}'";
}
}

/**
* Thrown when the encryption of a file using a certificate fails
*
*/
class encryptFailedException extends Exception
{
private $contentFile;
private $certFile;

public function __construct($contentFile, $certFile)


{
$this->contentFile = $contentFile;
$this->certFile = $certFile;
}

public function getContentFile()


{
return $this->contentFile;
}

public function getCertFile()


{
return $this->certFile;
}

public function __toString()


{
return "Failed to encrypt file '{$this->contentFile}' with certificate file '{$this-
>certFile}'";
}
}

Securing PayPal Checkout button Page 14 of 17


?>

Securing PayPal Checkout button Page 15 of 17

You might also like