PHP & Google Checkout
I’ve been working on several projects lately that have involved Google Checkout integration on various levels. Besides a basic HTML integration you can get going in few seconds (just by copy and pasting the sample code from the documentation) you can also entirely integrate the checkout process with your websites through the Google Checkout API.
There are also sample classes for different languages (PHP, .NET, JSP etc) that allow you to receive responses from Google Checkout about a stage the checkout process is currently in (an order goes through many stages until it becomes processed and your customer’s credit card gets actually charged such as “REVIEWING”, “CHARGEABLE”, “CHARGING”, “CHARGED”) so you can update your local database accordingly.
There are few small errors in the sample class from Google though so I have decided to post the working version and explain briefly how to use it. Here’s a snippet from one of my projects (it’s actually a Zend Framework controller action):
-
public function responseHandlerAction()
-
{
-
// point to the correct directory
-
chdir(APPLICATION_PATH . '/../library/Google/Checkout');
-
// include all the required files
-
include('googlecart.php');
-
include('googleitem.php');
-
include('googleshipping.php');
-
include('googletax.php');
-
include('googleresponse.php');
-
include('googlerequest.php');
-
-
$merchant_id = 'your merchant id here…';
-
$merchant_key = 'your merchant key here…';
-
$server_type = 'sandbox'; // change this to anything other than 'sandbox' to go live
-
$currency = 'GBP'; // USD for dollar
-
-
$Gresponse = new GoogleResponse($merchant_id, $merchant_key);
-
-
$Grequest = new GoogleRequest($merchant_id, $merchant_key, $server_type, $currency);
-
-
// retrieve the XML sent in the HTTP POST request to the ResponseHandler
-
$xml_response = isset($HTTP_RAW_POST_DATA) ?
-
$HTTP_RAW_POST_DATA:file_get_contents("php://input");
-
if (get_magic_quotes_gpc()) {
-
$xml_response = stripslashes($xml_response);
-
}
-
list($root, $data) = $Gresponse->GetParsedXML($xml_response);
-
$Gresponse->SetMerchantAuthentication($merchant_id, $merchant_key);
-
-
$status = $Gresponse->HttpAuthentication();
-
if (!$status) {
-
die('authentication failed');
-
}
-
-
switch ($root) {
-
case 'new-order-notification':
-
-
/*
-
* $google_id = $data[$root]['google-order-number']['VALUE'];
-
* $items = $this->get_arr_result($data[$root]['shopping-cart']['items']['item']);
-
* foreach ($items as $item) {
-
* $id = $item['merchant-item-id']['VALUE'];
-
* // do something here…
-
* }
-
*/
-
-
$Gresponse->SendAck();
-
-
break;
-
case 'order-state-change-notification':
-
-
$new_financial_state = $data[$root]['new-financial-order-state']['VALUE'];
-
$new_fulfillment_order = $data[$root]['new-fulfillment-order-state']['VALUE'];
-
-
switch ($new_financial_state) {
-
case 'REVIEWING':
-
-
// do something here…
-
-
break;
-
case 'CHARGEABLE':
-
-
$Grequest->SendProcessOrder($data[$root]['google-order-number']['VALUE']);
-
$Grequest->SendChargeOrder($data[$root]['google-order-number']['VALUE'], '');
-
-
break;
-
case 'CHARGING':
-
-
// do something here…
-
-
break;
-
case 'CHARGED':
-
-
/*
-
* $google_id = $data[$root]['google-order-number']['VALUE'];
-
* do something here…
-
*/
-
-
break;
-
case 'PAYMENT_DECLINED':
-
-
// do something here…
-
-
break;
-
case 'CANCELLED':
-
-
// do something here…
-
-
break;
-
case 'CANCELLED_BY_GOOGLE':
-
-
$message = 'Sorry, your order is cancelled by Google'
-
$Grequest->SendBuyerMessage($data[$root]['google-order-number']['VALUE'], $message, true);
-
-
break;
-
default:
-
-
break;
-
}
-
-
switch ($new_fulfillment_order) {
-
case 'NEW':
-
-
// do something here…
-
-
break;
-
case 'PROCESSING':
-
-
// do something here…
-
-
break;
-
case 'DELIVERED':
-
-
// do something here…
-
-
break;
-
case 'WILL_NOT_DELIVER':
-
-
// do something here…
-
-
break;
-
default:
-
-
// do something here…
-
-
break;
-
}
-
-
$Gresponse->SendAck();
-
break;
-
case 'charge-amount-notification':
-
-
// do something here…
-
-
$Gresponse->SendAck();
-
-
break;
-
case 'chargeback-amount-notification':
-
-
// do something here…
-
-
$Gresponse->SendAck();
-
-
break;
-
case 'refund-amount-notification':
-
-
// do something here…
-
-
$Gresponse->SendAck();
-
-
break;
-
case 'risk-information-notification':
-
-
// do something here…
-
-
$Gresponse->SendAck();
-
-
break;
-
default:
-
-
// do something here…
-
-
$Gresponse->SendBadRequestStatus('Invalid or not supported Message');
-
-
break;
-
}
-
}
-
-
private function get_arr_result($child_node) {
-
$result = array();
-
if (isset($child_node)) {
-
if ($this->is_associative_array($child_node)) {
-
$result[] = $child_node;
-
} else {
-
foreach ($child_node as $curr_node){
-
$result[] = $curr_node;
-
}
-
}
-
}
-
return $result;
-
}
-
-
private function is_associative_array($var) {
-
return is_array ($var) && !is_numeric (implode('', array_keys($var)));
-
}
95% of the code above is taken from the responsehandler.php on this page. I have only made little modifications to make it all work because the original code contained few errors.
Now, how to make it all work? First, go here and download the latest sample code. Unzip the archive and copy all files except responsehandler.php and cartdemo.php to some location in your project (I just created a directory called ‘Google’ and put all files there in my library folder).
Second, you need to create a shopping cart or at least a checkout button that will take your customers to the Google Checkout page where they can pay for the product with their credit/debit cards. Here is just an example from one of my latest projects (a short excerpt of the checkout action):
-
// point to the correct directory
-
chdir(APPLICATION_PATH . '/../library/Google/Checkout');
-
// include all the required files
-
include('googlecart.php');
-
include('googleitem.php');
-
include('googleshipping.php');
-
include('googletax.php');
-
-
$merchant_id = 'xxxxxxxxxxxxxxxx';
-
$merchant_key = 'xxxxxxxxxxxxxxxxxxxxxx';
-
$server_type = 'sandbox';
-
$currency = 'GBP';
-
$cart = new GoogleCart($merchant_id, $merchant_key, $server_type,
-
$currency);
-
-
$item = new GoogleItem("Digital Item",
-
"Description",
-
1, // quantity
-
$price); // unit price
-
$item->SetMerchantItemId($id);
-
$item->SetEmailDigitalDelivery('true');
-
$cart->AddItem($item);
-
-
// <edit-cart-url>
-
$cart->SetEditCartUrl('http://mydomain.com/controller/action');
-
-
// "Return to xyz" link
-
$cart->SetContinueShoppingUrl('http://mydomain.com/controller/action');
-
-
// request buyer's phone number
-
$cart->SetRequestBuyerPhone(false);
-
-
$this->view->checkoutButton = $cart->CheckoutButtonCode('large',
-
true,
-
'en_US',
-
false);
Third, you need to configure your Google Checkout account to send callbacks to the response-handler action. Remember that when you are testing the integration in the sandbox, you can just use ordinary http:// URIs but when you go live, Google Checkout requires you to use https:// at least on the response-handler action URI.
The actual PHP integration depends on the website you want to integrate Google Checkout with so I’m not going to show you how to do that. I can give you some very basic guidelines though:
- I usually have a special table where I store all Google Checkout transactions. On the page with Google Checkout button I create a new row in the table and use the primary key to set a merchant item id ($item->SetMerchantItemId($id)). This helps me determine the transaction id in the response-handler action.
- In the “new-order-notification” callback I get the google order number and edit the transaction in the table based on the merchant item id I set earlier.
- In the “CHARGED” callback I mark the transaction in the table as finished based on its google order number (usually the table has a boolean field with default value 0 called “finished”, so I set it to 1).
I think you could have formatted your code better as when people copy and paste they have 180+ line numbers to remove from your revised response handler and also for people wishing to read and understand your codeflow you have this line aiming to a file which resides in your application on your server.
#
chdir(APPLICATION_PATH . ‘/../library/Google/Checkout’);
With regards Googles latest code examples though I myself have been studying and testing and they do appear to work correctly, though they could be simplified somewhat.
chdir(APPLICATION_PATH . ‘/../library/Google/Checkout’);
That line just points to the directory, where all Google Checkout files are located.
Regarding the (not)working official Google Checkout PHP files. They weren’t working for me until I made these few little modifications. I cannot say anything more because it’s a long time since I was integrating Google Checkout in one of my ZF apps so I don’t remember the details.
Thanks for your post I will be working on a project and plan to use Google Checkout I was wondering how ever if you have any experience integrating any other payment methods with Zend? Thanks again for the post.
Well,
I do have some limited experience with 2Checkout. I have integrated it into a website in the past but it was only a basic integration.