how to implement paypal in cakephp?

Here is an idea how to implement paypal in cakephp less than 5 mins? Answer is use Socket programming!! Yes, I found these very handy two classes from my friend Rajib Deb. So big big thanks for him.

Now step by step to implementation of this component.

Step 1: Create paypal.php file in /app/controllers/components/
Step 2: Paste this two class in paypal.php file

class HTTPRequest {

private $host;
private $path;
private $method;
private $port;
private $rawhost;

private $header;
private $content;
private $parsedHeader;

function __construct($host, $path, $method = 'POST', $ssl = false, $port = 0) {
$this->host = $host;
$this->rawhost = $ssl ? ("ssl://".$host) : $host;
$this->path = $path;
$this->method = strtoupper($method);
if ($port) {
$this->port = $port;
} else {
if (!$ssl) $this->port = 80; else $this->port = 443;
}
}

public function connect( $data = ''){
$fp = fsockopen($this->rawhost, $this->port);
if (!$fp) return false;
fputs($fp, "$this->method $this->path HTTP/1.1\r\n");
fputs($fp, "Host: $this->host\r\n");
//fputs($fp, "Content-type: $contenttype\r\n");
fputs($fp, "Content-length: ".strlen($data)."\r\n");
fputs($fp, "Connection: close\r\n");
fputs($fp, "\r\n");
fputs($fp, $data);

$responseHeader = '';
$responseContent = '';

do
{
$responseHeader.= fread($fp, 1);
}
while (!preg_match('/\\r\\n\\r\\n$/', $responseHeader));


if (!strstr($responseHeader, "Transfer-Encoding: chunked"))
{
while (!feof($fp))
{
$responseContent.= fgets($fp, 128);
}
}
else
{

while ($chunk_length = hexdec(fgets($fp)))
{
$responseContentChunk = '';

$read_length = 0;

while ($read_length < $chunk_length)
{
$responseContentChunk .= fread($fp, $chunk_length - $read_length);
$read_length = strlen($responseContentChunk);
}

$responseContent.= $responseContentChunk;

fgets($fp);

}

}

$this->header = chop($responseHeader);
$this->content = $responseContent;
$this->parsedHeader = $this->headerParse();

$code = intval(trim(substr($this->parsedHeader[0], 9)));

return $code;
}

function headerParse(){
$h = $this->header;
$a=explode("\r\n", $h);
$out = array();
foreach ($a as $v){
$k = strpos($v, ':');
if ($k) {
$key = trim(substr($v,0,$k));
$value = trim(substr($v,$k+1));
if (!$key) continue;
$out[$key] = $value;
} else
{
if ($v) $out[] = $v;
}
}
return $out;
}

public function getContent() {return $this->content;}
public function getHeader() {return $this->parsedHeader;}


}


class PaypalComponent extends Object {

var $endpoint;
var $host;
var $gate;
var $returnSuccessUrl;
var $returnCancelUrl;
var $paypalUserName;
var $paypalPassword;
var $paypalSignature;

function __construct($real = false) {
$this->endpoint = '/nvp';
if ($real) {
/*
* Production Credentials
*/
$this->host = "api-3t.paypal.com";
$this->gate = 'https://www.paypal.com/cgi-bin/webscr?';
} else {
/*
* Sendbox Credentials for testing purpose
*/
$this->host = "api-3t.sandbox.paypal.com";
$this->gate = 'https://www.sandbox.paypal.com/cgi-bin/webscr?';
}
}

/**
* @return string URL of the "success" page
*/
function getReturnTo() {
return $this->returnSuccessUrl;
}

/**
* @return string URL of the "cancel" page
*/
function getReturnToCancel() {
return $this->returnCancelUrl;
}

/**
* @return HTTPRequest
*/
function response($data){
$r = new HTTPRequest($this->host, $this->endpoint, 'POST', true);
$result = $r->connect($data);
if ($result->paypalUserName)
$data['PWD'] = $this->paypalPassword;
$data['SIGNATURE'] = $this->paypalSignature;
$data['VERSION'] = '51.0';
if(!function_exists('http_build_query')) {
$query = $this->http_build_query_php4($data);
} else {
$query = http_build_query($data);
}
return $query;
}
function http_build_query_php4($data,$b='',$c=0){
if (!is_array($data)) return false;
foreach ((array)$data as $key=>$value){
$pair[]=$key."=".urlencode($value);
}
return implode("&amp;",$pair);
}

/**
* Main payment function
*
* If OK, the customer is redirected to PayPal gateway
* If error, the error info is returned
*
* @param float $amount Amount (2 numbers after decimal point)
* @param string $desc Item description
* @param string $invoice Invoice number (can be omitted)
* @param string $currency 3-letter currency code (USD, GBP, CZK etc.)
*
* @return array error info
*/
function doExpressCheckout($amount, $desc, $invoice='', $currency='USD'){
$data = array(
'PAYMENTACTION' =>'Sale',
'AMT' =>$amount,
'RETURNURL' =>$this->getReturnTo(),
'CANCELURL'  =>$this->getReturnToCancel(),
'DESC'=>$desc,
'NOSHIPPING'=>"1",
'ALLOWNOTE'=>"1",
'CURRENCYCODE'=>$currency,
'METHOD' =>'SetExpressCheckout');

$data['CUSTOM'] = $amount.'|'.$currency.'|'.$invoice;
if ($invoice) $data['INVNUM'] = $invoice;

$query = $this->buildQuery($data);

$result = $this->response($query);

if (!$result) return false;
$response = $result->getContent();
$return = $this->responseParse($response);
if ($return['ACK'] == 'Success') {
header('Location: '.$this->gate.'cmd=_express-checkout&amp;useraction=commit&amp;token='.$return['TOKEN'].'');
die();
}
return($return);
}

function getCheckoutDetails($token){
$data = array(
'TOKEN' => $token,
'METHOD' =>'GetExpressCheckoutDetails');
$query = $this->buildQuery($data);

$result = $this->response($query);

if (!$result) return false;
$response = $result->getContent();
$return = $this->responseParse($response);
return($return);
}
function doPayment(){
$token = $_GET['token'];
$payer = $_GET['PayerID'];
$details = $this->getCheckoutDetails($token);
if (!$details) return false;
list($amount,$currency,$invoice) = explode('|',$details['CUSTOM']);
$data = array(
'PAYMENTACTION' => 'Sale',
'PAYERID' => $payer,
'TOKEN' =>$token,
'AMT' => $amount,
'CURRENCYCODE'=>$currency,
'METHOD' =>'DoExpressCheckoutPayment');
$query = $this->buildQuery($data);

$result = $this->response($query);

if (!$result) return false;
$response = $result->getContent();
$return = $this->responseParse($response);

/*
* [AMT] => 10.00
* [CURRENCYCODE] => USD
* [PAYMENTSTATUS] => Completed
* [PENDINGREASON] => None
* [REASONCODE] => None
*/

return($return);
}

function getScheme() {
$scheme = 'http';
if (isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on') {
$scheme .= 's';
}
return $scheme;
}

function responseParse($resp){
$a=explode("&amp;", $resp);
$out = array();
foreach ($a as $v){
$k = strpos($v, '=');
if ($k) {
$key = trim(substr($v,0,$k));
$value = trim(substr($v,$k+1));
if (!$key) continue;
$out[$key] = urldecode($value);
} else {
$out[] = $v;
}
}
return $out;
}

function doDirectPayment($Order) {

$Order['METHOD'] = 'DoDirectPayment';

$query = $this->buildQuery($Order);

$result = $this->response($query);
if (!$result)
return false;
$response = $result->getContent();
return $this->responseParse($response);

}
}

Step 3: In your controller add

var $components=array( ‘Paypal’);

Step 4: For PayPal Express Check Out use somthing like

public function expressPaypalCheckOut(){
$this->Paypal->paypalUserName = $pyapal_settings['user'];
$this->Paypal->paypalPassword = $pyapal_settings['password'];
$this->Paypal->paypalSignature = $pyapal_settings['signature'];
$this->Paypal->returnSuccessUrl = "/success/url/returnByPaypal/pay?csid=" . session_id();
$this->Paypal->returnCancelUrl = "/cancel/url/returnByPaypal/cancel?csid=".session_id();
$ret = ($this->Paypal->doExpressCheckout($user_info["amount"], 'Access to source code library','','EUR')); // use USD for dollar
}

Step 5: For PayPal Direct Payment use somthing like

$order = array(
'PAYMENTACTION'=>'Sale',
'AMT'=> ($FREQUEST->postvalue('amount')/100),
'CREDITCARDTYPE'=>$FREQUEST->postvalue('card_type'),
'ACCT'=>$FREQUEST->postvalue('creditCard1'),
'EXPDATE'=>$FREQUEST->postvalue('expire_month').$FREQUEST->postvalue('expire_year'),
'CVV2'=>$FREQUEST->postvalue('cvvno'),
'FIRSTNAME'=> $session_information["billto_array"]["firstname"],
'LASTNAME'=> $session_information["billto_array"]["lastname"],
'STREET'=> $session_information["billto_array"]["street_address"],
'CITY'=>$session_information["billto_array"]["city"],
'STATE'=> $session_information["billto_array"]["state"],
'ZIP'=> $session_information["billto_array"]["postcode"],
'COUNTRYCODE'=> $session_information["billto_array"]["country"]["iso_code_2"],
'CURRENCYCODE'=> 'USD'</code>

);

$this->Paypal->paypalUserName = $pyapal_settings['user'];
$this->Paypal->paypalPassword = $pyapal_settings['password'];
$this->Paypal->paypalSignature = $pyapal_settings['signature'];
$this->Paypal->returnSuccessUrl = "/success/url/returnByPaypal/pay?csid=" . session_id();
$this->Paypal->returnCancelUrl = "/cancel/url/returnByPaypal/cancel?csid=".session_id();
$ret = ($this->Paypal->doDirectPayment($order));
</blockquote>

<strong>6</strong> Now after getting the responds from PayPal you need to reconfigure again the PayPal settings something like
<blockquote>
public function returnByPaypal($callback = null){
if ($callback == 'cancel') {
			$this->redirect("your/cancel/page");
	        exit;
	    } else if ($callback == 'pay') {
               $pyapal_settings = Configure::read('paypal_settings');
			$this->Paypal->paypalUserName = $pyapal_settings['user'];
			$this->Paypal->paypalPassword = $pyapal_settings['password'];
			$this->Paypal->paypalSignature = $pyapal_settings['signature'];
			$paypalRespons = $this->Paypal->doPayment();
                        if($paypalRespons['ACK'] == 'Success'){
                             /* your code in here*/
                        }
            }
}

Well, thats it. Please consider some syntax error or other cause i am not testing these code yet!!! enjoy ;)

Inspired from Martin Maly’s Paypal Library

About Tanveer
RIA (Rich Internet Application) Developer with a wide variety of business applications. Particularly interested in client/server and relational database design. Always interested in migration projects, as well as close interaction with the DB manufacturers.

12 Responses to how to implement paypal in cakephp?

  1. I found a small error in line 72 see this while ($read_length header = chop($responseHeader);

    Falopa!

  2. Pingback: 2010 in review « Tanveer's Weblog

  3. Ankita says:

    I think two end braces are left at line 78. But really this code is very helpful. I am implementing it in my project.
    Thanks for the code.

  4. Hi! Tanveer,
    You have written good code here but there is some error in this code I just trying to make you notice over it:

    1. at line 72:
    while ($read_length header = chop($responseHeader);
    what is header here

    2. $this->buildQuery(); is undefined in your component.

    3. at line 161 : if ($resultpaypalUserName;
    Invalid syntax wont identify that how many lines is to come in the condition coz end braces also missing.

    Please Correct them I need to Use this script onto my Project.
    I shall be very thankful to you!

  5. Sav says:

    Hello Tanveer,
    Where to save step 4 and 5 contents in files?

    thanks

    • Tanveer says:

      Hi Sav,
      Step 4. is nothing but a method name in your controller where you want to call expressPaypalCheckOut()

      Step 5. is for Direct Payment. This step is also depends on your business logic and you can use in
      your controller. So make $order array first.
      $order = array( … ); Then, you must need to call:
      $this->Paypal->doDirectPayment($order);

      Feel free to drop comments if any!

      • Sav says:

        Hello Tanveer,
        I’m getting same error.
        1. at line 72:
        while ($read_length header = chop($responseHeader);

        thanks

  6. ianemv says:

    Interesting. I might try this method if the methods I’m trying to implement won’t work :)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 286 other followers