Mike Griffiths

Archive for September, 2009

Google Chrome OS

by Mike on Sep.11, 2009, under Findings

You might think of Google as your doorway to the Internet. Google is the search engine most people use to find what they’re looking for on the Internet. But the fact is, Google is a brand and the search is simply their flag ship product. Google releases new products regularly, they have well over 50 products; some of them are used every day by millions of users (Google Mail) and others are used occassionally by a few thousand users (Google Code Search).

It has since been released that Google has a new product on the way, a product that has been rumoured for some time now and it’s making a lot of people very excited, and a lot of people very nervous.

Google is releasing it’s own operating system.

The operating system (OS) will be know as Google Chrome OS (at least for the time being). It’s due for release in mid-2010. To begin with the OS will be used solely on netbooks, but it’s very likely to be brought into use on laptops and desktops very soon after.

Google have said that they are taking everything back to the drawing board and changing the way computers work. Most computers today are built using similar kernals, whether they’re Windows, Linux or Unix – the basic architecture is the same. It’s well known that Linux and Unix systems are more stable than other systems, but that doesn’t make them any more safe. All computers are prone to viruses, but Google believe they’ve come up with a way of stopping viruses, worms and malware on computers all together. It will be interesting to see how.

The OS itself will be tiny. The OS will simply work with the computers hardware to connect to the Internet and display web content. The good part about it is that it’s built for cloud computing. Cloud computing is a new term popping up more and more. It’s the term used to describe systems or software that are available on the Internet, but not at one central location. Google are already at the forefront of this technology with their products Google Mail – a webmail service – and Google Documents – a free browser-based version of Microsoft Office.

To do basic tasks on a Windows or Mac you need to install a hefty sized OS, which costs. You’ll then need licenses for your word processing or spreadsheet software, which is another cost again. You then need an email host and server set up, which can cost rental and can be difficult to set up. You’ll then need some where to store it, whether that’s a home network or your computers hard drives. The idea of Google’s OS is that you install the free Chrome OS, and that’s it. The OS comes with the web browser that you’ll need to do everything, from the browser you can access Google Mail, Google Documents and anything else you’ll need.

So essentially Google are releasing a package that is completely free, all you need is your hardware, which will be even cheaper when buying from vendors like PC World as they won’t be made to purchase the OS license fees.

All of this must be getting Microsoft and Apple a little worried. Google are known for getting things right, and with Microsoft’s track record of late deadlines and resource intensive software, and Apple’s reputation of being ridiculously over priced – both companies must have their tails between their legs. Even more so with the latest press release from Google that states a list of companies that Google will be working with on this project, including hardware manufacturers such as HP, Acer, Asus, Lenovo, Texas Instruments, Freescale and software vendor Adobe – but no mention of Dell or Intel.

In my personal opinion I believe that in 10 years time we’ll all be paying next to nothing for computers, but instead renting virtual space on a series of servers some where, and as the price of storage and bandwidth comes down it’s likely to get a lot cheaper for all of us.

Leave a Comment :, more...

PayPal IPN Example Code

by Mike on Sep.03, 2009, under Findings, Web Development

I’ve been using PayPal for web site payments for years now. I love the way you can just sign up for an account and begin taking payments quickly, unlike a lot of gateways where you need merchant accounts with banks and written permission and what not. I always recommend PayPal to my clients as it means minimal fuss and get’s their site online far faster.

One thing I’ve noticed though, is that there is no decent example code out their for their IPN (Instant Payment Notification) service, which informs your web application when a payment is made, so you can do whatever you need to do when the user pays; ship the product, send an email, send a download link, set their account to upgraded, whatever. So, quite simply, here’s mine…

It’s based on PayPal’s very old and out-dated example script. I’ve adapted it to work on today’s properly set up production servers and removed the causes of the massive amounts of Notices and Warnings PHP would spit out with the old code. It’s pretty simple to use, just edit the config vars at the top to suit yourself. It’s defaulted to the live set up. You can put your custom code to be executed when a successful payment is made around halfway down, just read the comments.


/*
 * @author Mike Griffiths
 * @website Mike-Griffiths.co.uk
 *
 * Use as you like but I'd appreciate a link back to my site and some credit.
 * Enjoy.
 *
 * Post comments on the blog post you found this code on (mike-griffiths.co.uk)
 * if you get stuck.
 *
 */

#############
# CONFIG
#############
$CONFIG = array();
/*
 * General
 */
$CONFIG['notify_email'] = "email@example.com"; // For debug info 

/*
 * Database
 */
$CONFIG['db_host'] = "localhost"; // Server, eg. 'localhost'
$CONFIG['db_user'] = "example";  // Username, eg. 'mike'
$CONFIG['db_pass'] = "example";  // Password, eg. '12345'
$CONFIG['db_name'] = "example";    // Database name 

############
# Script
############
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
    $value = urlencode(stripslashes($value));
    $req .= "&$key=$value";
}
// post back to PayPal system to validate
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; 

// If testing on Sandbox use:
//$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30); 

// assign posted variables to local variables
$item_name              = (empty($_POST['item_name']) ? '' : $_POST['item_name']);
$business               = (empty($_POST['business']) ? '' : $_POST['business']);
$item_number            = (empty($_POST['item_number']) ? '' : $_POST['item_number']);
$payment_status         = (empty($_POST['payment_status']) ? '' : $_POST['payment_status']);
$mc_gross               = (empty($_POST['mc_gross']) ? '' : $_POST['mc_gross']);
$payment_currency       = (empty($_POST['mc_currency']) ? '' : $_POST['mc_currency']);
$txn_id                 = (empty($_POST['txn_id']) ? '' : $_POST['txn_id']);
$receiver_email         = (empty($_POST['receiver_email']) ? '' : $_POST['receiver_email']);
$receiver_id            = (empty($_POST['receiver_id']) ? '' : $_POST['receiver_id']);
$quantity               = (empty($_POST['quantity']) ? '' : $_POST['quantity']);
$num_cart_items         = (empty($_POST['num_cart_items']) ? '' : $_POST['num_cart_items']);
$payment_date           = (empty($_POST['payment_date']) ? '' : $_POST['payment_date']);
$first_name             = (empty($_POST['first_name']) ? '' : $_POST['first_name']);
$last_name              = (empty($_POST['last_name']) ? '' : $_POST['last_name']);
$payment_type           = (empty($_POST['payment_type']) ? '' : $_POST['payment_type']);
$payment_status         = (empty($_POST['payment_status']) ? '' : $_POST['payment_status']);
$payment_gross          = (empty($_POST['payment_gross']) ? '' : $_POST['payment_gross']);
$payment_fee            = (empty($_POST['payment_fee']) ? '' : $_POST['payment_fee']);
$settle_amount          = (empty($_POST['settle_amount']) ? '' : $_POST['settle_amount']);
$memo                   = (empty($_POST['memo']) ? '' : $_POST['memo']);
$payer_email            = (empty($_POST['payer_email']) ? '' : $_POST['payer_email']);
$txn_type               = (empty($_POST['txn_type']) ? '' : $_POST['txn_type']);
$payer_status           = (empty($_POST['payer_status']) ? '' : $_POST['payer_status']);
$address_street         = (empty($_POST['address_street']) ? '' : $_POST['address_street']);
$address_city           = (empty($_POST['address_city']) ? '' : $_POST['address_city']);
$address_state          = (empty($_POST['address_state']) ? '' : $_POST['address_state']);
$address_zip            = (empty($_POST['address_zip']) ? '' : $_POST['address_zip']);
$address_country        = (empty($_POST['address_country']) ? '' : $_POST['address_country']);
$address_status         = (empty($_POST['address_status']) ? '' : $_POST['address_status']);
$item_number            = (empty($_POST['item_number']) ? '' : $_POST['item_number']);
$tax                    = (empty($_POST['tax']) ? '' : $_POST['tax']);
$option_name1           = (empty($_POST['option_name1']) ? '' : $_POST['option_name1']);
$option_selection1      = (empty($_POST['option_selection1']) ? '' : $_POST['option_selection1']);
$option_name2           = (empty($_POST['option_name2']) ? '' : $_POST['option_name2']);
$option_selection2      = (empty($_POST['option_selection2']) ? '' : $_POST['option_selection2']);
$for_auction            = (empty($_POST['for_auction']) ? '' : $_POST['for_auction']);
$invoice                = (empty($_POST['invoice']) ? '' : $_POST['invoice']);
$custom                 = (empty($_POST['custom']) ? '' : $_POST['custom']);
$notify_version         = (empty($_POST['notify_version']) ? '' : $_POST['notify_version']);
$verify_sign            = (empty($_POST['verify_sign']) ? '' : $_POST['verify_sign']);
$payer_business_name    = (empty($_POST['payer_business_name']) ? '' : $_POST['payer_business_name']);
$payer_id               = (empty($_POST['payer_id']) ? '' : $_POST['payer_id']);
$mc_currency            = (empty($_POST['mc_currency']) ? '' : $_POST['mc_currency']);
$mc_fee                 = (empty($_POST['mc_fee']) ? '' : $_POST['mc_fee']);
$exchange_rate          = (empty($_POST['exchange_rate']) ? '' : $_POST['exchange_rate']);
$settle_currency        = (empty($_POST['settle_currency']) ? '' : $_POST['settle_currency']);
$parent_txn_id          = (empty($_POST['parent_txn_id']) ? '' : $_POST['parent_txn_id']);
$pending_reason         = (empty($_POST['pending_reason']) ? '' : $_POST['pending_reason']);
$reason_code            = (empty($_POST['reason_code']) ? '' : $_POST['reason_code']); 

// subscription specific vars
$subscr_id           = $_POST['subscr_id'];
$subscr_date       = $_POST['subscr_date'];
$subscr_effective = $_POST['subscr_effective'];
$period1           = $_POST['period1'];
$period2           = $_POST['period2'];
$period3           = $_POST['period3'];
$amount1           = $_POST['amount1'];
$amount2           = $_POST['amount2'];
$amount3           = $_POST['amount3'];
$mc_amount1       = $_POST['mc_amount1'];
$mc_amount2       = $_POST['mc_amount2'];
$mc_amount3       = $_POST['mcamount3'];
$recurring           = $_POST['recurring'];
$reattempt           = $_POST['reattempt'];
$retry_at           = $_POST['retry_at'];
$recur_times       = $_POST['recur_times'];
$username           = $_POST['username'];
$password           = $_POST['password']; 

// auction specific vars
$for_auction           = $_POST['for_auction'];
$auction_closing_date = $_POST['auction_closing_date'];
$auction_multi_item   = $_POST['auction_multi_item'];
$auction_buyer_id        = $_POST['auction_buyer_id']; 

if (!$fp) {
    // HTTP ERROR
} else {
    fputs ($fp, $header . $req);
    while (!feof($fp)) {
        $res = fgets ($fp, 1024);
        if (strcmp ($res, "VERIFIED") == 0) {         

            //create MySQL connection
            $link = @mysql_connect($CONFIG['db_host'], $CONFIG['db_user'], $CONFIG['db_pass'])
            or die("Couldn't connect to MySQL:<br>" . mysql_error() . "<br>" . mysql_errno()); 

            //select database
            $db = @mysql_select_db($CONFIG['db_name'], $link)
            or die("Couldn't select database:<br>" . mysql_error(). "<br>" . mysql_errno()); 

            $fecha = date("m")."/".date("d")."/".date("Y");
            $fecha = date("Y").date("m").date("d"); 

            //check if transaction ID has been processed before
            $checkquery = "select txnid from paypal_payment_info where txnid='".$txn_id."'";
            $sihay = mysql_query($checkquery) or die("Duplicate txn id check query failed:<br>" . mysql_error() . "<br>" . mysql_errno());
            $nm = mysql_num_rows($sihay); 

            if ($nm == 0){ 

                if ($txn_type == "cart"){
                    $strQuery = "insert into paypal_payment_info(paymentstatus,buyer_email,firstname,lastname,street,city,state,zipcode,country,mc_gross,mc_fee,memo,paymenttype,paymentdate,txnid,pendingreason,reasoncode,tax,datecreation) values ('".$payment_status."','".$payer_email."','".$first_name."','".$last_name."','".$address_street."','".$address_city."','".$address_state."','".$address_zip."','".$address_country."','".$mc_gross."','".$mc_fee."','".$memo."','".$payment_type."','".$payment_date."','".$txn_id."','".$pending_reason."','".$reason_code."','".$tax."','".$fecha."')";
                    $result = mysql_query($strQuery) or die("Cart - paypal_payment_info, Query failed:<br>" . mysql_error() . "<br>" . mysql_errno());
                    for ($i = 1; $i <= $num_cart_items; $i++) {
                        $itemname = "item_name".$i;
                        $itemnumber = "item_number".$i;
                        $on0 = "option_name1_".$i;
                        $os0 = "option_selection1_".$i;
                        $on1 = "option_name2_".$i;
                        $os1 = "option_selection2_".$i;
                        $quantity = "quantity".$i; 

                        $struery = "insert into paypal_cart_info(txnid,itemnumber,itemname,os0,on0,os1,on1,quantity,invoice,custom) values ('".$txn_id."','".$_POST[$itemnumber]."','".$_POST[$itemname]."','".$_POST[$on0]."','".$_POST[$os0]."','".$_POST[$on1]."','".$_POST[$os1]."','".$_POST[$quantity]."','".$invoice."','".$custom."')";
                        $result = mysql_query($struery) or die("Cart - paypal_cart_info, Query failed:<br>" . mysql_error() . "<br>" . mysql_errno()); 

                        ##############
                        ### BEGIN YOUR CUSTOM CODE FOR BUY NOW VERIFIED (cart)
                        ############## 

                        ##############
                        ### END YOUR CUSTOM CODE FOR BUY NOW VERIFIED (cart)
                        ##############
                    }
                } else {
                    $strQuery = "insert into paypal_payment_info(paymentstatus,buyer_email,firstname,lastname,street,city,state,zipcode,country,mc_gross,mc_fee,itemnumber,itemname,os0,on0,os1,on1,quantity,memo,paymenttype,paymentdate,txnid,pendingreason,reasoncode,tax,datecreation) values ('".$payment_status."','".$payer_email."','".$first_name."','".$last_name."','".$address_street."','".$address_city."','".$address_state."','".$address_zip."','".$address_country."','".$mc_gross."','".$mc_fee."','".$item_number."','".$item_name."','".$option_name1."','".$option_selection1."','".$option_name2."','".$option_selection2."','".$quantity."','".$memo."','".$payment_type."','".$payment_date."','".$txn_id."','".$pending_reason."','".$reason_code."','".$tax."','".$fecha."')";
                    $result = mysql_query("insert into paypal_payment_info(paymentstatus,buyer_email,firstname,lastname,street,city,state,zipcode,country,mc_gross,mc_fee,itemnumber,itemname,os0,on0,os1,on1,quantity,memo,paymenttype,paymentdate,txnid,pendingreason,reasoncode,tax,datecreation) values ('".$payment_status."','".$payer_email."','".$first_name."','".$last_name."','".$address_street."','".$address_city."','".$address_state."','".$address_zip."','".$address_country."','".$mc_gross."','".$mc_fee."','".$item_number."','".$item_name."','".$option_name1."','".$option_selection1."','".$option_name2."','".$option_selection2."','".$quantity."','".$memo."','".$payment_type."','".$payment_date."','".$txn_id."','".$pending_reason."','".$reason_code."','".$tax."','".$fecha."')") or die("Default - paypal_payment_info, Query failed:<br>" . mysql_error() . "<br>" . mysql_errno()); 

                    ##############
                    ### BEGIN YOUR CUSTOM CODE FOR BUY NOW VERIFIED (simple)
                    ############## 

                    ##############
                    ### END YOUR CUSTOM CODE FOR BUY NOW VERIFIED (simple)
                    ##############
                } 

                echo "Verified";
                mail($CONFIG['notify_email'], "VERIFIED IPN", "$res\n $req\n $strQuery\n $struery\n  $strQuery2"); 

            } else {
                // send an email
                mail($CONFIG['notify_email'], "VERIFIED DUPLICATED TRANSACTION", "$res\n $req \n $strQuery\n $struery\n  $strQuery2");
            } 

            //subscription handling branch
            if ( $txn_type == "subscr_signup"  ||  $txn_type == "subscr_payment"  ) { 

                // insert subscriber payment info into paypal_payment_info table
                $strQuery = "insert into paypal_payment_info(paymentstatus,buyer_email,firstname,lastname,street,city,state,zipcode,country,mc_gross,mc_fee,memo,paymenttype,paymentdate,txnid,pendingreason,reasoncode,tax,datecreation) values ('".$payment_status."','".$payer_email."','".$first_name."','".$last_name."','".$address_street."','".$address_city."','".$address_state."','".$address_zip."','".$address_country."','".$mc_gross."','".$mc_fee."','".$memo."','".$payment_type."','".$payment_date."','".$txn_id."','".$pending_reason."','".$reason_code."','".$tax."','".$fecha."')";
                $result = mysql_query($strQuery) or die("Subscription - paypal_payment_info, Query failed:<br>" . mysql_error() . "<br>" . mysql_errno()); 

                // insert subscriber info into paypal_subscription_info table
                $strQuery2 = "insert into paypal_subscription_info(subscr_id , sub_event, subscr_date ,subscr_effective,period1,period2, period3, amount1 ,amount2 ,amount3,  mc_amount1,  mc_amount2,  mc_amount3, recurring, reattempt,retry_at, recur_times, username ,password, payment_txn_id, subscriber_emailaddress, datecreation) values ('".$subscr_id."', '".$txn_type."','".$subscr_date."','".$subscr_effective."','".$period1."','".$period2."','".$period3."','".$amount1."','".$amount2."','".$amount3."','".$mc_amount1."','".$mc_amount2."','".$mc_amount3."','".$recurring."','".$reattempt."','".$retry_at."','".$recur_times."','".$username."','".$password."', '".$txn_id."','".$payer_email."','".$fecha."')";
                $result = mysql_query($strQuery2) or die("Subscription - paypal_subscription_info, Query failed:<br>" . mysql_error() . "<br>" . mysql_errno()); 

                ##############
                ### BEGIN YOUR CUSTOM CODE FOR SUBSCRIPTION VERIFIED
                ############## 

                ##############
                ### END YOUR CUSTOM CODE FOR SUBSCRIPTION VERIFIED
                ############## 

                mail($CONFIG['notify_email'], "VERIFIED IPN", "$res\n $req\n $strQuery\n $struery\n  $strQuery2"); 

            }         

        // if the IPN POST was 'INVALID'...do this
        } else if (strcmp ($res, "INVALID") == 0) {
            // log for manual investigation
            mail($CONFIG['notify_email'], "INVALID IPN", "$res\n $req");
        }
    }
    fclose ($fp);
}

You’ll need the following SQL too…

# Table structure for table `paypal_cart_info` 	#

CREATE TABLE `paypal_cart_info` (
  `txnid` varchar(30) NOT NULL default '',
  `itemname` varchar(255) NOT NULL default '',
  `itemnumber` varchar(50) default NULL,
  `os0` varchar(20) default NULL,
  `on0` varchar(50) default NULL,
  `os1` varchar(20) default NULL,
  `on1` varchar(50) default NULL,
  `quantity` char(3) NOT NULL default '',
  `invoice` varchar(255) NOT NULL default '',
  `custom` varchar(255) NOT NULL default ''
) TYPE=MyISAM;

# Table structure for table `paypal_subscription_info` #

CREATE TABLE `paypal_subscription_info` (
  `subscr_id` varchar(255) NOT NULL default '',
  `sub_event` varchar(50) NOT NULL default '',
  `subscr_date` varchar(255) NOT NULL default '',
  `subscr_effective` varchar(255) NOT NULL default '',
  `period1` varchar(255) NOT NULL default '',
  `period2` varchar(255) NOT NULL default '',
  `period3` varchar(255) NOT NULL default '',
  `amount1` varchar(255) NOT NULL default '',
  `amount2` varchar(255) NOT NULL default '',
  `amount3` varchar(255) NOT NULL default '',
  `mc_amount1` varchar(255) NOT NULL default '',
  `mc_amount2` varchar(255) NOT NULL default '',
  `mc_amount3` varchar(255) NOT NULL default '',
  `recurring` varchar(255) NOT NULL default '',
  `reattempt` varchar(255) NOT NULL default '',
  `retry_at` varchar(255) NOT NULL default '',
  `recur_times` varchar(255) NOT NULL default '',
  `username` varchar(255) NOT NULL default '',
  `password` varchar(255) default NULL,
  `payment_txn_id` varchar(50) NOT NULL default '',
  `subscriber_emailaddress` varchar(255) NOT NULL default '',
  `datecreation` date NOT NULL default '0000-00-00'
) TYPE=MyISAM;

# Table structure for table `paypal_payment_info` #

CREATE TABLE `paypal_payment_info` (
  `firstname` varchar(100) NOT NULL default '',
  `lastname` varchar(100) NOT NULL default '',
  `buyer_email` varchar(100) NOT NULL default '',
  `street` varchar(100) NOT NULL default '',
  `city` varchar(50) NOT NULL default '',
  `state` char(3) NOT NULL default '',
  `zipcode` varchar(11) NOT NULL default '',
  `memo` varchar(255) default NULL,
  `itemname` varchar(255) default NULL,
  `itemnumber` varchar(50) default NULL,
  `os0` varchar(20) default NULL,
  `on0` varchar(50) default NULL,
  `os1` varchar(20) default NULL,
  `on1` varchar(50) default NULL,
  `quantity` char(3) default NULL,
  `paymentdate` varchar(50) NOT NULL default '',
  `paymenttype` varchar(10) NOT NULL default '',
  `txnid` varchar(30) NOT NULL default '',
  `mc_gross` varchar(6) NOT NULL default '',
  `mc_fee` varchar(5) NOT NULL default '',
  `paymentstatus` varchar(15) NOT NULL default '',
  `pendingreason` varchar(10) default NULL,
  `txntype` varchar(10) NOT NULL default '',
  `tax` varchar(10) default NULL,
  `mc_currency` varchar(5) NOT NULL default '',
  `reasoncode` varchar(20) NOT NULL default '',
  `custom` varchar(255) NOT NULL default '',
  `country` varchar(20) NOT NULL default '',
  `datecreation` date NOT NULL default '0000-00-00'
) TYPE=MyISAM;
6 Comments more...

Downtime Prevention

by Mike on Sep.01, 2009, under Findings, General, Web Development

Downtime Prevention is not a new concept. It does seem, however, that there aren’t too many places doing it right.

One place I have found exceeding expectation though, is a web site offering downtime alerts and downtime notifications. The clever system checks your web site periodically for PHP errors, Apache errors, 404’s, 403’s, poor re-directs, etc. It also pings the server, does some TCP checks and does some HTTP header checks, all to see if your site is online and working as it should be. If there are no errors then all is kept silnet, if something is found though, you’ll receive a free email. These emails are limited to 4 a day so you don’t get 2,000 emails in your inbox should your site go down over night.

As a lot of us aren’t around 24/7 to check our emails but want to know the second our site goes down, this downtime alerts service also offers SMS alerts to your mobile phone. Where these alerts aren’t entirely free, they are cheap and capped to one a day, so you know you’re not going to be shelling out an arm and a leg. It’s dead easy to add credits and worth while doing in my opinion: your site might only go down once every 6 months and it’s oh so very easy to miss an email (be it because of spam, poor filters, or just human error), but you’ll never miss an SMS and you’ll see it straight away. You’re also able to do something about it straight away; with your phone in your hand ready to make the important phone call to your tech guy!

So, enough plugging – go and sign up.

Leave a Comment :, , , , more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post.