Tuesday, January 20, 2009

Two Kinds

There are 2 types of employees:
One believe that his boss is the devil.
Another believe that his boss is a nice man.
The one believe that his boss is devil will work to not make his boss angry. He will do everything strictly according to rule and wash all his backsides.
The one believe that his boss is a nice man can work more freely and able to accept more challenge, learn from mistakes and can give more ideas.

There are 2 types of bosses:
One believe all his workers are lazy and don't want to work and not trust worthy.
Another believe that his workers are committed and love to work.
The formal boss will implement ways to track every hour and monitor all activities of his employees.
The later boss will trust his workers, delegate important work and give freedoms to his employees, believing that the people he hired will do a good work.

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


Thursday, February 16, 2006

PHP Email Injection

Recently some of my PHP scripts have been attacked by spammer using email injection to send 100,000s of spammails...

If you are not familiar with email injection, here is the explaination.

The attack in PHP is through the mail() function.

The mail function accepts 4 arguments:
mail($sendto, $subject, $message, $header).

Some scripts accept an email address from the input form to configure the mail header so that the recipiant will see the "From" email address.

e.g.
mail("info@target.com", $_POST["subject"], $_POST["message"],
"From: ".$_POST["email"]);

?>

The accepting of input form value to build the email header opens a loophold for spammer, which enable them to add additional header information like Cc or Bcc.

For example, the spammer create his/her own version of the contact form which submit to your PHP script. In that contact form, he create <textarea name="'email'"></textarea> in replace with your original text box and fill in the following text into the <textarea>

john@123.com
Cc: abc@xyz.com,def@xyz.com,ght@xyz.com

In this case, your $_POST["email"] variable will contain the following text:
"john@123.com\nCc: abc@xyz.com,def@xyz.com,ght@xyz.com"
and your email header becomes
"From: john@123.com\nCc: abc@xyz.com,def@xyz.com,ght@xyz.com"

This eventually cause the mail function to send mail to info@target.com but also Cc to
abc@xyz.com, def@xyz.com and ght@xyz.com.

In order to solve this problem, we have to always double check the $_POST["email"] variable to make sure there aren't any vulnerable characters (' "" \n etc...) which can be use for injection attack. One of the suggestion is as below

if (preg_match(' /[\r\n,;\'"]/ ', $_POST['email'])) {
exit('Invalid email address');
}
else {
//code to send the mail
}

Thursday, December 29, 2005

MySQL Licenses

MySQL is offering 2 type of licenses: Commercial and Free (GNU/GPL).

Commercial license, as what it named, you need to pay to use at a very "affordable" price of USD595/server/year.

The good news is, there is a free version under the GNU/GPL license, which most of the hosting companies provide. In addition the features of the free version are ALL same as the commercial license. So is it really a good news? The answer might disappoint you.

As stated in MySQL website: "MySQL is free use for those who are 100% GPL", means if I'm using MySQL for my web application, all my source code must be 100% GPL (open source), which also means that my clients can actually modify and resale the codes that I developed for them! As for .NET and Java developer, you might also need to handover the full source code to your client if you are using the free version.
(Ref: http://www.mysql.com/company/legal/licensing/opensource-license.html)

Alternatively you can use PostgreSQL or FireBird in replace of MySQL. These 2 database servers are totally free to use without any restriction (Pls doublecheck yourself for the license agreements :P)