Sunday, April 16, 2006

Standard PayPal PHP Integration

This article contains 3 section ...
I. General Architecture
II. PayPal Settings
III. PHP Integration

The integration uses CURL to connect to PayPal server. I assume you are familiar with CURL functions for PHP. You can visit PHP manual at http://sg.php.net/manual/en/ref.curl.php for more information.







I. GENERAL ARCHITECTURE


This is my proposed architecture...

After the checkout process in your website, you redirect the buyer to the PayPal website to make payment. After making the payment (or cancel the payment), PayPal will redirect the buyer back to your website.

During the checkout process, you may...
- Calculate product total and shipment cost
- Gather buyer delivery and billing information

At point A you may...
- Store the order information temporary in database (with status set as "Pending"). This can help to prevent information lost while PayPal redirect the buyer back to your website.
- Submit payment information to PayPal website through HTTP Post. (Will be explained later)
- We will assume this page as http://www.yourmerchant.com/saveorder.php

Point B is where PayPal return to your website. Here you will need to check the payment status by sending request to PayPal server. (Will be explainted later). After checking the status (Success or Failed), you can update the status of the order and reroute your buyer to either a thankyou page or cancel page. We will assume this page as http://www.yourmerchant.com/paypal_return.php

Note that PayPal will redirect the buyer to a cancel page if he/she click the "Cancel" link in PayPal page. We will assume this page as http://www.yourmerchant.com/paypal_cancel.php






II. PayPal Settings
You will need to have PayPal premier or business to accept online payment.

For web developers, you can test the integration using the testing environment called sanbox. To setup developer account...
1. Visit developer.paypal.com
2. Sign-up a developer account and login to PayPal Developer Center
3. Create new PayPal Premier/Business account at SandBox


To setup PayPal to accept website payment...
1. Login to PayPal at www.paypal.com or http://www.sandbox.paypal.com/ (Testing environment)

2. From the "Profile" section under "My Account" tab, click "Website Payment Preferences"


3. In "Website Payment Preferences" page, make the following changes and save the setting
- Auto Return to On
- Return URL to the absolute URL of the page you want PayPal to return to
- Payment Data Transfer to On
- PayPal Account Optional to On. This will allow your buyer to make payment directly using Credit Card if he/she does not have a PayPal account.

4. Visit back the "Website Payment Preferences" page and copy the "Identity Token" under "Payment Data Transfer". We will use this token to send request to PayPal at point B of General Architecture.





III. PHP Integration
This is the sample code for saveorder.php


$desc = //set to the order description to be appear on the PayPal website;
$orderno = //set to unique order number;
$nettotal = //set to productTotal + shipmentFee + tax;
$_SESSION["ss_last_orderno"] = $orderno;

//Save order information to database using the unique order number with status set as Pending...


$url = "https://www.sandbox.paypal.com/cgi-bin/webscr"; //Test
//$url = "https://www.paypal.com/cgi-bin/webscr"; //Live
$ppAcc = "leepeng@forecepts.com"; //PayPal account email
$cancelURL = "http://www.yourmerchant.com/paypal_cancel.php";
$returnURL = "http://www.yourmerchant.com/paypal_return.php";

$buffer =
"<form action='$url' method='post' name='frmPayPal'>\n".
"<input type='hidden' name='business' value='$ppAcc'>\n".
"<input type='hidden' name='cmd' value='_xclick'>\n".
"<input type='hidden' name='item_name' value='$desc'>\n".
"<input type='hidden' name='item_number' value='$orderno'>\n".
"<input type='hidden' name='amount' value='$nettotal'>\n".
"<input type='hidden' name='no_shipping' value='1'>\n".
"<input type='hidden' name='currency_code' value='USD'>\n".
"<input type='hidden' name='handling' value='0'>\n".
"<input type='hidden' name='cancel_return' value='$cancelURL'>\n".
"<input type='hidden' name='return' value='$returnURL'>\n".
"</form>\n".
"<script language='javascript'>document.frmPayPal.submit();"</script>\n";

echo($buffer);


This is the sample code for paypal_return.php


$orderno = $_SESSION["ss_last_orderno"];
$ppAcc = "leepeng@forecepts.com";
$at = "Kjz22GB8NmlPJNxrGl1ha6z4tkU4DYsH1-_zh5KuZuOqy8CUIUPBkCIKCBy"; //PDT Identity Token
$url = "https://www.sandbox.paypal.com/cgi-bin/webscr"; //Test
//$url = "https://www.paypal.com/cgi-bin/webscr"; //Live
$tx = $_REQUEST["tx"]; //this value is return by PayPal
$cmd = "_notify-synch";
$post = "tx=$tx&at=$at&amp;cmd=$cmd";

//Send request to PayPal server using CURL
$ch = curl_init ($url);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_HEADER, 0);
curl_setopt ($ch, CURLOPT_TIMEOUT, 30);
curl_setopt ($ch, CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
curl_setopt ($ch, CURLOPT_POSTFIELDS, $post);

$result = curl_exec ($ch); //returned result is key-value pair string
$error = curl_error($ch);

if (curl_errno($ch) != 0) //CURL error
exit("ERROR: Failed updating order. PayPal PDT service failed.");

$longstr = str_replace("\r", "", $result);
$lines = split("\n", $longstr);

//parse the result string and store information to array
if ($lines[0] == "SUCCESS") {
//successful payment
$ppInfo = array();
for ($i=1; $i<count($lines); $i++) {
$parts = split("=", $lines[$i]);
if (count($parts)==2) {
$ppInfo[$parts[0]] = urldecode($parts[1]);
}
}

$curtime = gmdate("d/m/Y H:i:s");
//capture the PayPal returned information as order remarks
$oremarks =
"##$curtime##\n".
"PayPal Transaction Information...\n".
"Txn Id: ".$ppInfo["txn_id"]."\n".
"Txn Type: ".$ppInfo["txn_type"]."\n".
"Item Number: ".$ppInfo["item_number"]."\n".
"Payment Date: ".$ppInfo["payment_date"]."\n".
"Payment Type: ".$ppInfo["payment_type"]."\n".
"Payment Status: ".$ppInfo["payment_status"]."\n".
"Currency: ".$ppInfo["mc_currency"]."\n".
"Payment Gross: ".$ppInfo["payment_gross"]."\n".
"Payment Fee: ".$ppInfo["payment_fee"]."\n".
"Payer Email: ".$ppInfo["payer_email"]."\n".
"Payer Id: ".$ppInfo["payer_id"]."\n".
"Payer Name: ".$ppInfo["first_name"]." ".$ppInfo["last_name"]."\n".
"Payer Status: ".$ppInfo["payer_status"]."\n".
"Country: ".$ppInfo["residence_country"]."\n".
"Business: ".$ppInfo["business"]."\n".
"Receiver Email: ".$ppInfo["receiver_email"]."\n".
"Receiver Id: ".$ppInfo["receiver_id"]."\n";

//Update database using $orderno, set status to Paid
//Send confirmation email to buyer and notification email to merchant
//Redirect to thankyou page
}

//Payment failed
else {
//Delete order information
//Redirect to failed page
}

Below are the websites done by me which uses PayPal
- www.anglers-proshop.com
- www.fishnpetpro.com
- www.admixture.com

If you are interest to acquire eCommerce service, pls feel free to contact my company at info@forecepts.com


18 Comments:

Blogger test said...

Thanks! The paypal documentation is not organized and having everything in one page helped.

Regards,
Arijit

5:02 AM  
Blogger Mark said...

This is a nice doc. This the only place where I found the paypal redirection without letting the customer see the intermediate redirection page. Nice simple trick of javascript. I would use this in my project.
Thanks mate
-mark
UK and USA Wholesalers & Dropshippers

5:17 AM  
Blogger Thomas Manning said...

There seems to be a bug in paypal return.

$post = "tx=$tx&at=$at&cmd=$cmd";

The '&' in this string causes the paypal sandbox to not recognise the cmd an hence the request returns a 'You must login page'.

I changed it to:

$post = "tx=$tx&at=$at&cmd=$cmd";

And it all worked fine. Thanks for the script; the & did cause me a few hours of frustration but this is far easier to use than what paypal presents.

9:02 PM  
Blogger Thomas Manning said...

Oh my comment didnt work cause it convert & a m p; into a & anyway.

I was trying to say. Watch out for the 'a m p ;' whithout spaces in the $post string. Replace it with a &

$post = "tx=$tx&at=$at'&a m p;'cmd=$cmd";

I hope this made some sense.

9:04 PM  
Blogger Thomas Manning said...

This comment has been removed by the author.

9:04 PM  
Blogger Unknown said...

Great tutorial Lee, thanks for your hardwork.

I have had trouble getting it to work though. It fails and does the else from the if $lines[0] == "SUCCESS".

A load of Paypal variables are in the URL of the browser on the return page though so its return some info.. you got any ideas how to trouble shoot this?

Thanks for your time

2:21 AM  
Blogger Unknown said...

I recommend PHP Express Checkout Wizard to simplify PayPal Express Checkout integration: PHP Express Checkout Wizard.

4:04 AM  
Blogger Unknown said...

really very nice article
tons of thanks

8:14 PM  
Blogger Alex said...

Undefined index: tx

PayPal doesn't sent the tx index in the $_REQUEST anymore?

That's why the script fails - any idea how to fix this?

4:20 AM  
Blogger Debjeet said...

Thanx for the post...and big thnx to Tom for spoting the 'ampersand' bug!!

3:36 PM  
Blogger Unknown said...

Great tutorial Lee, thanks for your hardwork.Really your blogger content is good..............

12:49 PM  
Blogger KoolKabin said...

that's a nice tutorial i found after search for few hours

12:53 PM  
Blogger KoolKabin said...

just checking stuffs on Outsourcing Nepal

12:57 PM  
Blogger eddel may said...

This comment has been removed by the author.

4:55 PM  
Blogger eddel may said...

I cant make it work :(
It is giving me a page that i still have to login to sandbox to continue, cant go to its success result.

can anyone help me? :(

4:56 PM  
Blogger rama said...

i cant send order details for more than one products with this.. can anyone help me

3:18 PM  
Blogger Unknown said...

I have trouble when getting it to work though. It fails and give $lines[0] == "FAIL" on response page.

8:14 PM  
Anonymous Anonymous said...

Thanks for sharing. MsgClub brings SMS API PHP integration for sending bulk SMS to the prospective clients and also the existing customers. This is the best and one-stop solution to all your business marketing needs.

8:24 PM  

Post a Comment

<< Home