HOW TO INSTALL GOOGLE CHECKOUT MODULE FOR OSC (v1.4.5_CCS) If you haven't read the README file yet, please read it first. NOTE: This will work with New OSCommercer v2.2. RC1 http://www.oscommerce.com/solutions/downloads The only file modified for v2.2RC1 is: catalog/checkout_payment.php IMPORTANT: Uninstall and re install the module. If not, many new configuration will not be enabled. -------------------------------------------------------------------------------- FRESH INSTALL ============= There are two installation options you need to choose from, so please read carefully to determine which option is right for you. OPTION A: ========= If you have the basic osCommerce installation without any other modules or add-on's, simply copy the provided files into your osCommerce system, preserving the file structure. For your reference, here is the list of files you need to copy over to your system: OSC_DIR: CHANGELOG INSTALLATION.txt README.txt states.jpg UPGRADE OSC_DIR/catalog: checkout_payment.php gc_return.php login.php shopping_cart.php OSC_DIR/catalog/admin: htaccess.php modules.php orders.php OSC_DIR/catalog/admin/includes/functions: general.php OSC_DIR/catalog/googlecheckout: gcheckout.php index.html responsehandler.php shipping_methods_ccs.php shipping_methods.php OSC_DIR/catalog/googlecheckout/library: googlecart.php googleitem.php googlelog.php googlemerchantcalculations.php googlerequest.php googleresponse.php googleresult.php googleshipping.php googletax.php index.html OSC_DIR/catalog/googlecheckout/library/xml-processing: gc_xmlbuilder.php gc_xmlparser.php index.html OSC_DIR/catalog/googlecheckout/logs: index.html response_error.log response_message.log OSC_DIR/catalog/googlecheckout/shipping_generator: index.php multigenerator.php multishipping_generator.js multishipping_generator.php README shipping_method_generator.php OSC_DIR/catalog/googlecheckout/shipping_metrics: readme ship_metrics shipping_metrics_commandline.php shipping_metrics.log OSC_DIR/catalog/includes/languages/english/modules/payment: googlecheckout.php OSC_DIR/catalog/includes/languages/espanol/modules/payment: googlecheckout.php OSC_DIR/catalog/includes/languages/german/modules/payment: googlecheckout.php OSC_DIR/catalog/includes/modules/payment: googlecheckout.php * Note: If you applied a patch or manually modified the files to disable register_globals, go for Option B. OPTION B: ========= If you have other modules installed on your osCommerce installation, replacing your existing files might break your existing installation. In this case, you need to edit the existing files manually. For this option, follow the instructions below: I. Copy the following new files into your existing system, preserving the file structure: ----------------------------------------------------------------------------------------- OSC_DIR: CHANGELOG INSTALLATION.txt README.txt states.jpg UPGRADE OSC_DIR/catalog: gc_return.php OSC_DIR/catalog/admin: htaccess.php OSC_DIR/catalog/googlecheckout: gcheckout.php index.html responsehandler.php shipping_methods_ccs.php shipping_methods.php OSC_DIR/catalog/googlecheckout/library: googlecart.php googleitem.php googlelog.php googlemerchantcalculations.php googlerequest.php googleresponse.php googleresult.php googleshipping.php googletax.php index.html OSC_DIR/catalog/googlecheckout/library/xml-processing: gc_xmlbuilder.php gc_xmlparser.php index.html OSC_DIR/catalog/googlecheckout/logs: index.html response_error.log response_message.log OSC_DIR/catalog/googlecheckout/shipping_generator: index.php multigenerator.php multishipping_generator.js multishipping_generator.php README shipping_method_generator.php OSC_DIR/catalog/googlecheckout/shipping_metrics: readme ship_metrics shipping_metrics_commandline.php shipping_metrics.log OSC_DIR/catalog/includes/languages/english/modules/payment: googlecheckout.php OSC_DIR/catalog/includes/languages/espanol/modules/payment: googlecheckout.php OSC_DIR/catalog/includes/languages/german/modules/payment: googlecheckout.php OSC_DIR/catalog/includes/modules/payment: googlecheckout.php II. Manually edit the following files from your system as instructed below: --------------------------------------------------------------------------- OSC_DIR/catalog/admin/includes/functions: general.php OSC_DIR/catalog/admin: modules.php orders.php OSC_DIR/catalog: checkout_payment.php login.php shopping_cart.php ---------------------------------------------------------------------------- 1. /catalog/admin/includes/functions/general.php LINE 758 ============================================================================ ADD: // ** GOOGLE CHECKOUT** // Function to store configuration values(shipping options) using // checkboxes in the Administration Tool // carrier calculation // perhaps this function must be moved to googlecheckout class, is not too general function gc_cfg_select_CCshipping($key_value, $key = '') { //add ropu // i get all the shipping methods available! global $PHP_SELF,$language,$module_type; require_once (DIR_FS_CATALOG . 'includes/modules/payment/googlecheckout.php'); $googlepayment = new googlecheckout(); $javascript = ""; $string .= $javascript; $key_values = explode( ", ", $key_value); foreach($googlepayment->cc_shipping_methods_names as $CCSCode => $CCSName){ $name = (($key) ? 'configuration[' . $key . '][]' : 'configuration_value'); $string .= "
" . $CCSName . ""."\n"; foreach($googlepayment->cc_shipping_methods[$CCSCode] as $type => $methods) { if (is_array($methods) && !empty($methods)) { $string .= '
     '. $type .'
'; $string .= 'Def. Value | Fix Charge | Variable | Method Name'; foreach($methods as $method => $method_name) { $string .= '
'; // default value $value = gc_compare($CCSCode . $method. $type , $key_values, "_CCS:", '1.00|0|0'); $values = explode('|',$value); $string .= DEFAULT_CURRENCY . ': '; $string .= DEFAULT_CURRENCY . ': '; $string .= '% '; $string .= ''."\n"; $string .= $method_name; } } } } return $string; } function gc_cfg_select_multioption($select_array, $key_value, $key = '') { for ($i=0; $i'; return $string; } // Custom Function to store configuration values (shipping default values) function gc_compare($key, $data, $sep="_VD:", $def_ret='1') { foreach($data as $value) { list($key2, $valor) = explode($sep, $value); if($key == $key2) return $valor; } return $def_ret; } // perhaps this function must be moved to googlecheckout class, is not too general function gc_cfg_select_shipping($select_array, $key_value, $key = '') { //add ropu // i get all the shipping methods available! global $PHP_SELF,$language,$module_type; $module_directory = DIR_FS_CATALOG_MODULES . 'shipping/'; $file_extension = substr($PHP_SELF, strrpos($PHP_SELF, '.')); $directory_array = array(); if ($dir = @dir($module_directory)) { while ($file = $dir->read()) { if (!is_dir($module_directory . $file)) { if (substr($file, strrpos($file, '.')) == $file_extension) { $directory_array[] = $file; } } } sort($directory_array); $dir->close(); } $installed_modules = array(); $select_array = array(); for ($i=0, $n=sizeof($directory_array); $i<$n; $i++) { $file = $directory_array[$i]; include_once(DIR_FS_CATALOG_LANGUAGES . $language . '/modules/shipping/' . $file); include_once($module_directory . $file); $class = substr($file, 0, strrpos($file, '.')); if (tep_class_exists($class)) { $module = new $class; //echo $class; if ($module->check() > 0) { $select_array[$module->code] = array('code' => $module->code, 'title' => $module->title, 'description' => $module->description, 'status' => $module->check()); } } } require_once (DIR_FS_CATALOG . 'includes/modules/payment/googlecheckout.php'); $googlepayment = new googlecheckout(); $ship_calcualtion_mode = (count(array_keys($select_array)) > count(array_intersect($googlepayment->shipping_support, array_keys($select_array)))) ? true : false; if(!$ship_calcualtion_mode) { return '
'. GOOGLECHECKOUT_TABLE_NO_MERCHANT_CALCULATION . ''; } $javascript = ""; $string .= $javascript; $key_values = explode( ", ", $key_value); foreach($select_array as $i => $value){ if ( $select_array[$i]['status'] && !in_array($select_array[$i]['code'], $googlepayment->shipping_support) ) { $name = (($key) ? 'configuration[' . $key . '][]' : 'configuration_value'); $string .= "
" . $select_array[$i]['title'] . ""."\n"; if (is_array($googlepayment->mc_shipping_methods[$select_array[$i]['code']])) { foreach($googlepayment->mc_shipping_methods[$select_array[$i]['code']] as $type => $methods) { if (is_array($methods) && !empty($methods)) { $string .= '
     '. $type .''; foreach($methods as $method => $method_name) { $string .= '
'; // default value $value = gc_compare($select_array[$i]['code'] . $method. $type , $key_values, 1); $string .= ' WITH: Processing before delivery if(strpos($order->info['payment_method'], 'Google')!= -1 && $order->info['orders_status'] == GC_STATE_PROCESSING){ echo '
Shipping Information
Tracking:
Carrier:
'; } ?> ---------------------------------------------------------------------------- 3b. /catalog/admin/orders.php LINE 40 ============================================================================ REPLACE: if ( ($check_status['orders_status'] != $status) || tep_not_null($comments)) { tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . tep_db_input($status) . "', last_modified = now() where orders_id = '" . (int)$oID . "'"); $customer_notified = '0'; if (isset($HTTP_POST_VARS['notify']) && ($HTTP_POST_VARS['notify'] == 'on')) { $notify_comments = ''; if (isset($HTTP_POST_VARS['notify_comments']) && ($HTTP_POST_VARS['notify_comments'] == 'on')) { $notify_comments = sprintf(EMAIL_TEXT_COMMENTS_UPDATE, $comments) . "\n\n"; } $email = STORE_NAME . "\n" . EMAIL_SEPARATOR . "\n" . EMAIL_TEXT_ORDER_NUMBER . ' ' . $oID . "\n" . EMAIL_TEXT_INVOICE_URL . ' ' . tep_catalog_href_link(FILENAME_CATALOG_ACCOUNT_HISTORY_INFO, 'order_id=' . $oID, 'SSL') . "\n" . EMAIL_TEXT_DATE_ORDERED . ' ' . tep_date_long($check_status['date_purchased']) . "\n\n" . $notify_comments . sprintf(EMAIL_TEXT_STATUS_UPDATE, $orders_status_array[$status]); tep_mail($check_status['customers_name'], $check_status['customers_email_address'], EMAIL_TEXT_SUBJECT, $email, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS); $customer_notified = '1'; } tep_db_query("insert into " . TABLE_ORDERS_STATUS_HISTORY . " (orders_id, orders_status_id, date_added, customer_notified, comments) values ('" . (int)$oID . "', '" . tep_db_input($status) . "', now(), '" . tep_db_input($customer_notified) . "', '" . tep_db_input($comments) . "')"); $order_updated = true; } WITH: if ( ($check_status['orders_status'] != $status) || tep_not_null($comments)) { tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . tep_db_input($status) . "', last_modified = now() where orders_id = '" . (int)$oID . "'"); // ** GOOGLE CHECKOUT ** chdir("./.."); require_once(DIR_WS_LANGUAGES . $language . '/modules/payment/googlecheckout.php'); $payment_value= MODULE_PAYMENT_GOOGLECHECKOUT_TEXT_TITLE; $num_rows = tep_db_num_rows(tep_db_query("select google_order_number from google_orders where orders_id= ". (int)$oID)); if($num_rows != 0) { $customer_notified = google_checkout_state_change($check_status, $status, $oID, (@$_POST['notify']=='on'?1:0), (@$_POST['notify_comments']=='on'?$comments:'')); } $customer_notified = isset($customer_notified)?$customer_notified:'0'; // ** END GOOGLE CHECKOUT ** if (isset($_POST['notify']) && ($_POST['notify'] == 'on')) { $notify_comments = ''; if (isset($_POST['notify_comments']) && ($_POST['notify_comments'] == 'on') && tep_not_null($comments)) { $notify_comments = EMAIL_TEXT_COMMENTS_UPDATE . $comments . "\n\n"; } // ** GOOGLE CHECKOUT ** $force_email = false; if($num_rows != 0 && (strlen(htmlentities(strip_tags($notify_comments))) > GOOGLE_MESSAGE_LENGTH && MODULE_PAYMENT_GOOGLECHECKOUT_USE_CART_MESSAGING == 'True')) { $force_email = true; $messageStack->add_session(GOOGLECHECKOUT_WARNING_SYSTEM_EMAIL_SENT, 'warning'); } if($num_rows == 0 || $force_email) { //send emails, not a google order or configured to use both messaging systems $email = STORE_NAME . "\n" . EMAIL_SEPARATOR . "\n" . EMAIL_TEXT_ORDER_NUMBER . ' ' . $oID . "\n" . EMAIL_TEXT_INVOICE_URL . ' ' . tep_catalog_href_link(FILENAME_CATALOG_ACCOUNT_HISTORY_INFO, 'order_id=' . $oID, 'SSL') . "\n" . EMAIL_TEXT_DATE_ORDERED . ' ' . tep_date_long($check_status['date_purchased']) . "\n\n" . $notify_comments . sprintf(EMAIL_TEXT_STATUS_UPDATE, $orders_status_array[$status]); tep_mail($check_status['customers_name'], $check_status['customers_email_address'], EMAIL_TEXT_SUBJECT, $email, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS); $customer_notified = '1'; //send extra emails } } tep_db_query("insert into " . TABLE_ORDERS_STATUS_HISTORY . " (orders_id, orders_status_id, date_added, customer_notified, comments) values ('" . (int)$oID . "', '" . tep_db_input($status) . "', now(), '" . tep_db_input($customer_notified) . "', '" . tep_db_input($comments) . "')"); $order_updated = true; } ---------------------------------------------------------------------------- 3c. /catalog/admin/orders.php LINE 14 ============================================================================ ADD: /* ** GOOGLE CHECKOUT **/ define('GC_STATE_NEW', 100); define('GC_STATE_PROCESSING', 101); define('GC_STATE_SHIPPED', 102); define('GC_STATE_REFUNDED', 103); define('GC_STATE_SHIPPED_REFUNDED', 104); define('GC_STATE_CANCELED', 105); function google_checkout_state_change($check_status, $status, $oID, $cust_notify, $notify_comments) { global $db,$messageStack, $orders_statuses; define('API_CALLBACK_ERROR_LOG', DIR_FS_CATALOG. "/googlecheckout/logs/response_error.log"); define('API_CALLBACK_MESSAGE_LOG', DIR_FS_CATALOG . "/googlecheckout/logs/response_message.log"); include_once(DIR_FS_CATALOG.'/includes/modules/payment/googlecheckout.php'); include_once(DIR_FS_CATALOG.'/googlecheckout/library/googlerequest.php'); $googlepayment = new googlecheckout(); $Grequest = new GoogleRequest($googlepayment->merchantid, $googlepayment->merchantkey, MODULE_PAYMENT_GOOGLECHECKOUT_MODE== 'https://sandbox.google.com/checkout/' ?"sandbox":"production", DEFAULT_CURRENCY); $Grequest->SetLogFiles(API_CALLBACK_ERROR_LOG, API_CALLBACK_MESSAGE_LOG); $google_answer = tep_db_fetch_array(tep_db_query("SELECT go.google_order_number, go.order_amount, o.customers_email_address, gc.buyer_id, o.customers_id FROM " . $googlepayment->table_order . " go inner join " . TABLE_ORDERS . " o on go.orders_id = o.orders_id inner join " . $googlepayment->table_name . " gc on gc.customers_id = o.customers_id WHERE go.orders_id = '" . (int)$oID ."' group by o.customers_id order by o.orders_id desc")); $google_order = $google_answer['google_order_number']; $amount = $google_answer['order_amount']; // If status update is from Google New -> Google Processing on the Admin UI // this invokes the processing-order and charge-order commands // 1->Google New, 2-> Google Processing if($check_status['orders_status'] == GC_STATE_NEW && $status == GC_STATE_PROCESSING && $google_order != '') { list($curl_status,) = $Grequest->SendChargeOrder($google_order, $amount); if($curl_status != 200) { $messageStack->add_session(GOOGLECHECKOUT_ERR_SEND_CHARGE_ORDER, 'error'); } else { $messageStack->add_session(GOOGLECHECKOUT_SUCCESS_SEND_CHARGE_ORDER, 'success'); } list($curl_status,) = $Grequest->SendProcessOrder($google_order); if($curl_status != 200) { $messageStack->add_session(GOOGLECHECKOUT_ERR_SEND_PROCESS_ORDER, 'error'); } else { $messageStack->add_session(GOOGLECHECKOUT_SUCCESS_SEND_PROCESS_ORDER, 'success'); } } // If status update is from Google Processing or Google Refunded -> Google Shipped on the Admin UI // this invokes the deliver-order and archive-order commands // 2->Google Processing or Google Refunded, 3-> Google Shipped (refunded) else if(($check_status['orders_status'] == GC_STATE_PROCESSING || $check_status['orders_status'] == GC_STATE_REFUNDED) && ($status == GC_STATE_SHIPPED || $status == GC_STATE_SHIPPED_REFUNDED ) && $google_order != '') { $carrier = $tracking_no = ""; // Add tracking Data if(isset($_POST['carrier_select']) && ($_POST['carrier_select'] != 'select') && isset($_POST['tracking_number']) && !empty($_POST['tracking_number'])) { $carrier = $_POST['carrier_select']; $tracking_no = $_POST['tracking_number']; $comments = GOOGLECHECKOUT_STATE_STRING_TRACKING ."\n" . GOOGLECHECKOUT_STATE_STRING_TRACKING_CARRIER . $_POST['carrier_select'] ."\n" . GOOGLECHECKOUT_STATE_STRING_TRACKING_NUMBER . $_POST['tracking_number'] . ""; tep_db_query("insert into " . TABLE_ORDERS_STATUS_HISTORY . " (orders_id, orders_status_id, date_added, customer_notified, comments) values ('" . (int)$oID . "', '" . tep_db_input(($check_status['orders_status']==GC_STATE_REFUNDED ?GC_STATE_SHIPPED_REFUNDED:GC_STATE_SHIPPED)) . "', now(), '" . tep_db_input($cust_notify) . "', '" . tep_db_input($comments) . "')"); } list($curl_status,) = $Grequest->SendDeliverOrder($google_order, $carrier, $tracking_no, ($cust_notify==1)?"true":"false"); if($curl_status != 200) { $messageStack->add_session(GOOGLECHECKOUT_ERR_SEND_DELIVER_ORDER, 'error'); } else { $messageStack->add_session(GOOGLECHECKOUT_SUCCESS_SEND_DELIVER_ORDER, 'success'); } list($curl_status,) = $Grequest->SendArchiveOrder($google_order); if($curl_status != 200) { $messageStack->add_session(GOOGLECHECKOUT_ERR_SEND_ARCHIVE_ORDER, 'error'); } else { $messageStack->add_session(GOOGLECHECKOUT_SUCCESS_SEND_ARCHIVE_ORDER, 'success'); } } // If status update is to Google Canceled on the Admin UI // this invokes the cancel-order and archive-order commands else if($check_status['orders_status'] != GC_STATE_CANCELED && $status == GC_STATE_CANCELED && $google_order != '') { if($check_status['orders_status'] != GC_STATE_NEW){ list($curl_status,) = $Grequest->SendRefundOrder($google_order, 0, GOOGLECHECKOUT_STATE_STRING_ORDER_CANCELED ); if($curl_status != 200) { $messageStack->add_session(GOOGLECHECKOUT_ERR_SEND_REFUND_ORDER, 'error'); } else { $messageStack->add_session(GOOGLECHECKOUT_SUCCESS_SEND_REFUND_ORDER, 'success'); } } else { // Tell google witch is the OSC's internal order Number list($curl_status,) = $Grequest->SendMerchantOrderNumber($google_order, $oID); if($curl_status != 200) { $messageStack->add_session(GOOGLECHECKOUT_ERR_SEND_MERCHANT_ORDER_NUMBER, 'error'); } else { $messageStack->add_session(GOOGLECHECKOUT_SUCCESS_SEND_MERCHANT_ORDER_NUMBER, 'success'); } } // Is the order is not archive, I do it if($check_status['orders_status'] != GC_STATE_SHIPPED && $check_status['orders_status'] != GC_STATE_SHIPPED_REFUNDED){ list($curl_status,) = $Grequest->SendArchiveOrder($google_order); if($curl_status != 200) { $messageStack->add_session(GOOGLECHECKOUT_ERR_SEND_ARCHIVE_ORDER, 'error'); } else { $messageStack->add_session(GOOGLECHECKOUT_SUCCESS_SEND_ARCHIVE_ORDER, 'success'); } } // Cancel the order list($curl_status,) = $Grequest->SendCancelOrder($google_order, GOOGLECHECKOUT_STATE_STRING_ORDER_CANCELED, $notify_comments); if($curl_status != 200) { $messageStack->add_session(GOOGLECHECKOUT_ERR_SEND_CANCEL_ORDER, 'error'); } else { $messageStack->add_session(GOOGLECHECKOUT_SUCCESS_SEND_CANCEL_ORDER, 'success'); } } else if($google_order != '' && $check_status['orders_status'] != $status){ $statuses = array(); foreach($orders_statuses as $status_array){ $statuses[$status_array['id']] = $status_array['text']; } $messageStack->add_session( sprintf(GOOGLECHECKOUT_ERR_INVALID_STATE_TRANSITION, $statuses[$check_status['orders_status']], $statuses[$status], $statuses[$check_status['orders_status']]), 'error'); } // Send Buyer's message if($cust_notify==1 && isset($notify_comments) && !empty($notify_comments)) { $cust_notify_ok = '0'; if(!((strlen(htmlentities(strip_tags($notify_comments))) > GOOGLE_MESSAGE_LENGTH) && MODULE_PAYMENT_GOOGLECHECKOUT_USE_CART_MESSAGING=='True')){ list($curl_status,) = $Grequest->sendBuyerMessage($google_order, $notify_comments, "true"); if($curl_status != 200) { $messageStack->add_session(GOOGLECHECKOUT_ERR_SEND_MESSAGE_ORDER, 'error'); $cust_notify_ok = '0'; } else { $messageStack->add_session(GOOGLECHECKOUT_SUCCESS_SEND_MESSAGE_ORDER, 'success'); $cust_notify_ok = '1'; } if(strlen(htmlentities(strip_tags($notify_comments))) > GOOGLE_MESSAGE_LENGTH) { $messageStack->add_session( sprintf(GOOGLECHECKOUT_WARNING_CHUNK_MESSAGE, GOOGLE_MESSAGE_LENGTH), 'warning'); } } // Cust notified return $cust_notify_ok; } // Cust notified return '0'; } // ** END GOOGLE CHECKOUT ** ---------------------------------------------------------------------------- 4. /catalog/checkout_payment.php LINE 222 ============================================================================ REPLACE: $selection = $payment_modules->selection(); WITH: // ** GOOGLE CHECKOUT ** // Skips Google checkout as a payment option on the payments page since that option // is provided in the checkout page $selection = $payment_modules->selection(); for($i=0, $n=sizeof($selection); $i<$n; $i++) { if($selection[$i]['id'] == 'googlecheckout') { array_splice($selection, $i, 1); break; } } // ** END GOOGLE CHECKOUT ** ---------------------------------------------------------------------------- 5. /catalog/login.php LINE 203 ============================================================================ REPLACE: WITH: ---------------------------------------------------------------------------- 6. /catalog/shopping_cart.php LINE 197 ============================================================================ REPLACE: ' . tep_image_button('button_checkout.gif', IMAGE_BUTTON_CHECKOUT) . ''; ?> WITH: ' . tep_image_button('button_checkout.gif', IMAGE_BUTTON_CHECKOUT) . ''; ?>