Google Checkout Merchant Center, enter %url as the callback URL for this site. This will allow Ubercart to communicate with Google Checkout.', array('!checkout_url' => $checkout_url, '%url' => url('google_checkout', array('absolute' => TRUE)))); break; } return $output; } function uc_google_checkout_menu() { $items = array(); $items['admin/store/settings/google_checkout'] = array( 'title' => 'Google Checkout settings', 'description' => 'Set merchant ID and key for Google Checkout.', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_google_checkout_settings'), 'access arguments' => array('administer store'), 'type' => MENU_NORMAL_ITEM, 'file' => 'uc_google_checkout.admin.inc', ); $items['admin/store/settings/google_checkout/account'] = array( 'title' => 'Account', 'type' => MENU_DEFAULT_LOCAL_TASK, ); $items['admin/store/settings/google_checkout/shipping'] = array( 'title' => 'Shipping', 'description' => 'Calculate shipping charges for orders through Google Checkout.', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_google_checkout_shipping_settings'), 'access arguments' => array('administer store'), 'type' => MENU_LOCAL_TASK, 'file' => 'uc_google_checkout.admin.inc', ); $items['admin/store/settings/google_checkout/taxes'] = array( 'title' => 'Taxes', 'description' => 'Calculate taxes for orders through Google Checkout.', 'page callback' => 'drupal_get_form', 'page arguments' => array('uc_google_checkout_taxes_settings'), 'access arguments' => array('administer store'), 'type' => MENU_LOCAL_TASK, 'file' => 'uc_google_checkout.admin.inc', ); $items['google_checkout'] = array( 'page callback' => 'uc_google_checkout_callback', 'access callback' => 'uc_google_checkout_callback_access', 'type' => MENU_CALLBACK, 'file' => 'uc_google_checkout.pages.inc', ); $items['admin/store/orders/%uc_order/google_checkout'] = array( 'title callback' => 'uc_google_checkout_terminal_title', 'title arguments' => array(3), 'description' => 'Process a credit card payment or refund through Google Checkout.', 'page callback' => 'uc_google_checkout_terminal', 'page arguments' => array(3), 'access arguments' => array('manual payments'), 'type' => MENU_CALLBACK, 'file' => 'uc_google_checkout.admin.inc', ); return $items; } function uc_google_checkout_callback_access() { return TRUE; } function uc_google_checkout_terminal_title($order) { return t('Google Checkout terminal: Order @order_id', array('@order_id' => $order->order_id)); } function uc_google_checkout_init() { // When an order comes in from Google Checkout, we need to unset some // $_SESSION data. Since this isn't done under the customer's user, we // do it when they next load a page. global $user; $users = variable_get('uc_google_checkout_order_users', array()); if (isset($users[$user->uid])) { unset($_SESSION['cart_order'], $_SESSION['do_complete'], $_SESSION['new_user'], $users[$user->uid]); variable_set('uc_google_checkout_order_users', $users); } global $conf; $conf['i18n_variables'][] = 'uc_google_checkout_order_cancel_reason'; } function uc_google_checkout_theme() { return array( 'uc_google_checkout_shipping_settings' => array( 'arguments' => array('form' => NULL), 'file' => 'uc_google_checkout.admin.inc', ), 'uc_google_checkout_taxes_settings' => array( 'arguments' => array('form' => NULL), 'file' => 'uc_google_checkout.admin.inc', ), ); } function uc_google_checkout_form_alter(&$form, $form_state, $form_id) { if (uc_product_is_product_form($form)) { $node = $form['#node']; if (is_object($node) && $form_id == $node->type .'_node_form' && uc_product_is_product($node->type)) { $policy_url = 'https://checkout.google.com/support/sell/bin/answer.py?answer=75724'; $form['google_checkout'] = array('#type' => 'fieldset', '#title' => t('Google Checkout settings'), '#collapsible' => TRUE, '#collapsed' => TRUE, ); $form['google_checkout']['gc_salable'] = array('#type' => 'checkbox', '#title' => t('Conforms to Google Checkout content policies.'), '#default_value' => isset($node->gc_salable) ? $node->gc_salable : TRUE, '#description' => t('To be a Google Checkout approved merchant, your items must conform to the Google Checkout content policies found here.', array('!url' => $policy_url)), ); } } elseif ($form_id == 'uc_payment_methods_form') { // Make sure no one enables this for Ubercart checkout. $form['pmtable']['google_checkout']['uc_payment_method_google_checkout_checkout']['#disabled'] = TRUE; $form['pmtable']['google_checkout']['uc_payment_method_google_checkout_checkout']['#value'] = FALSE; } elseif ($form_id == 'uc_payment_by_order_form') { // Don't use Google Checkout for manual payments either. unset($form['payments']['new']['method']['#options']['google_checkout']); } elseif ($form_id == 'uc_order_view_update_form') { $form['#submit'][] = 'uc_google_checkout_notify_update'; } elseif ($form_id == 'uc_store_format_settings_form') { $form['currency']['uc_currency_code']['#description'] .= ' '. t('Google Checkout only accepts the following currencies: @list', array('@list' => implode(', ', _uc_google_checkout_currency_codes()))); } } /** * Implementation of hook_nodeapi(). */ function uc_google_checkout_nodeapi(&$node, $op) { if (uc_product_is_product($node->type)) { switch ($op) { case 'insert': case 'update': if (isset($node->gc_salable)) { if (!$node->revision) { db_query("DELETE FROM {uc_gc_products} WHERE vid = %d", $node->vid); } db_query("INSERT INTO {uc_gc_products} (vid, nid, gc_salable) VALUES (%d, %d, %d)", $node->vid, $node->nid, $node->gc_salable); } break; case 'load': $salable = db_result(db_query("SELECT gc_salable FROM {uc_gc_products} WHERE vid = %d", $node->vid)); if ($salable === FALSE) { $salable = TRUE; } return array('gc_salable' => $salable); break; case 'delete': db_query("DELETE FROM {uc_gc_products} WHERE nid = %d", $node->nid); break; case 'delete revision': db_query("DELETE FROM {uc_gc_products} WHERE vid = %d", $node->vid); break; } } } /****************************************************************************** * Hook Functions (Ubercart) * ******************************************************************************/ function uc_google_checkout_cart_pane() { $panes[] = array( 'id' => 'uc_google_checkout', 'title' => t('Google Checkout'), 'enabled' => TRUE, 'weight' => 1, 'body' => '
'. drupal_get_form('uc_google_checkout_cart_form') .'
', ); return $panes; } function uc_google_checkout_order_pane() { $panes[] = array( 'id' => 'email_allowed', 'callback' => 'uc_google_checkout_pane_email_allowed', 'title' => t('Marketing preferences'), 'desc' => t("Display the customer's preferences about mass-marketing."), 'class' => 'pos-left', 'weight' => 4, 'show' => array('view', 'customer'), ); return $panes; } function uc_google_checkout_line_item() { $items[] = array( 'id' => 'gc_coupon', 'title' => t('Google Checkout Coupon'), 'stored' => TRUE, 'calculated' => TRUE, 'weight' => 2, ); $items[] = array( 'id' => 'gc_gift_certificate', 'title' => t('Google Checkout Gift Certificate'), 'stored' => TRUE, 'calculated' => TRUE, 'weight' => 2, ); return $items; } function uc_google_checkout_order($op, &$arg1, $arg2) { switch ($op) { case 'load': $result = db_query("SELECT * FROM {uc_gc_orders} WHERE order_id = %d", $arg1->order_id); if ($gc = db_fetch_object($result)) { $arg1->google_order_number = $gc->gc_order_number; $arg1->financial_state = $gc->financial_state; $arg1->fulfillment_state = $gc->fulfillment_state; $arg1->gc_total = $gc->gc_total; } break; case 'can_update': if (is_null($arg1->google_order_number) || isset($_SESSION['google_updates']) && $_SESSION['google_updates']) { return TRUE; } switch ($arg2) { case 'canceled': if (uc_google_checkout_cancel_order($arg1)) { drupal_set_message(t('Cancel order request sent to Google Checkout. The order will be updated momentarily.')); } else { drupal_set_message(t('Order is not canceled in Google Checkout.')); } return FALSE; } break; } } /** * Implementation of hook_payment_method(). */ function uc_google_checkout_payment_method() { $methods[] = array( 'id' => 'google_checkout', 'name' => t('Google Checkout'), 'title' => t('Google Checkout'), 'desc' => t('Express payment with Google Checkout.'), 'callback' => 'uc_payment_method_google_checkout', 'weight' => 1, 'checkout' => FALSE, 'backend' => FALSE, ); return $methods; } function uc_google_checkout_payment_gateway() { $gateways[] = array( 'id' => 'google_checkout', 'title' => t('Google Checkout'), 'description' => t('Express payment with Google Checkout.'), 'google_checkout' => 'uc_google_checkout_charge', ); return $gateways; } function uc_google_checkout_shipment($op, $shipment) { switch ($op) { case 'save': $google_order_number = uc_google_checkout_get_google_number($shipment->order_id); if ($google_order_number && $shipment->is_new) { $xml_data = ''; foreach ($shipment->packages as $package) { if ($package->tracking_number) { $tracking_number = $package->tracking_number; } elseif ($shipment->tracking_number) { $tracking_number = $shipment->tracking_number; } if ($tracking_number) { foreach ($package->products as $product) { $xml_data .= ''; $xml_data .= ''; $xml_data .= ''. check_plain($product->nid .'|'. $product->model) .''; $xml_data .= ''; $xml_data .= ''; $xml_data .= ''; $xml_data .= ''. check_plain($shipment->carrier) .''; $xml_data .= ''. check_plain($tracking_number) .''; $xml_data .= ''; $xml_data .= ''; $xml_data .= ''; } } } if ($xml_data) { $request = ''; $request .= "\n"; $request .= ''; $request .= ''; $request .= $xml_data; $request .= ''; $request .= 'true'; $request .= ''; $response = uc_google_checkout_send_request('request', $request); } } break; case 'delete': $google_order_number = uc_google_checkout_get_google_number($shipment->order_id); if ($google_order_number) { foreach ($shipment->packages as $package) { foreach ($package->products as $product) { $reset_ids[] = check_plain($product->nid .'|'. $product->model); } } $request = ''; $request .= "\n"; $request .= ''; $request .= ''; foreach (array_unique($reset_ids) as $item_id) { $request .= ''; $request .= ''. $item_id .''; $request .= ''; } $request .= ''; $request .= 'false'; $request .= ''; } $response = uc_google_checkout_send_request('request', $request); break; } } /****************************************************************************** * Callback Functions, Forms, and Tables * ******************************************************************************/ function uc_google_checkout_cart_form() { if (variable_get('uc_google_checkout_mode', 'checkout') == 'checkout') { $merchant_id = variable_get('uc_google_checkout_merchant_id', ''); $checkout_url = 'https://checkout.google.com'; } else { $merchant_id = variable_get('uc_google_checkout_test_merchant_id', ''); $checkout_url = 'https://sandbox.google.com/checkout'; } if (!$merchant_id) { watchdog('google', 'Google Checkout is enabled, but no Merchant ID found.', array(), WATCHDOG_ERROR, 'admin/store/settings/google_checkout'); return; } // Hack to allow the image button to submit. if (isset($_POST['submit_x'])) { $form['submit'] = array( '#type' => 'submit', '#value' => 'submit', ); } $disable = FALSE; foreach (uc_cart_get_contents() as $item) { $product = node_load($item->nid); if (!$product->gc_salable) { $disable = TRUE; break; } } switch (variable_get('uc_google_checkout_button_size', 'large')) { case 'large': $width = 180; $height = 46; break; case 'medium': $width = 168; $height = 44; break; case 'small': $width = 160; $height = 43; break; } $form['submit_image'] = array( '#value' => ($disable ? '', ); $form['submit_help'] = array( '#value' => '
'. t('What is Google Checkout?') .'', ); return $form; } function uc_google_checkout_cart_form_submit($form, &$form_state) { global $user; $items = uc_cart_get_contents(); if (!is_array($items) || count($items) == 0) { drupal_set_message(t('You do not have any items in your shopping cart.')); return; } if (empty($_SESSION['cart_order'])) { $order = uc_order_new($user->uid); $_SESSION['cart_order'] = $order->order_id; } else { $order = new stdClass(); $order->uid = $user->uid; $order->order_id = $_SESSION['cart_order']; $order->primary_email = $user->mail; $order->order_status = uc_order_state_default('in_checkout'); } $order->products = $items; uc_order_save($order); uc_order_update_status($order->order_id, 'in_google_checkout'); $order->order_status = 'in_google_checkout'; $request = uc_google_checkout_cart_request($order); if ($response = uc_google_checkout_send_request('merchantCheckout', $request)) { $redirect = (string) $response->{'redirect-url'}; drupal_goto($redirect); } } function uc_google_checkout_cart_request($order) { if (variable_get('uc_google_checkout_mode', 'checkout') == 'checkout') { $merchant_id = variable_get('uc_google_checkout_merchant_id', ''); } else { $merchant_id = variable_get('uc_google_checkout_test_merchant_id', ''); } $output = ''; $output .= "\n"; if (count($order->products)) { $output .= ''; $output .= ''; $output .= ''; foreach ($order->products as $product) { $output .= ''; $output .= ''. check_plain($product->model) .''; $output .= ''. check_plain($product->title) .''; $output .= ''. $product->price .''; $output .= ''; if (!uc_cart_product_is_shippable($product)) { $output .= ''; $output .= 'PESSIMISTIC'; $output .= 'true'; $output .= ''; } $output .= ''. $product->qty .''; $output .= ''. $product->nid .'|'. $product->model .''; $output .= ''; } $output .= ''; $output .= ''; $output .= ''. uc_cart_get_id() .''; $output .= ''. $order->order_id .''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; if (uc_order_is_shippable($order)) { $companies = uc_google_checkout_shipping_companies(); $services = uc_google_checkout_shipping_services(); $shipping_options = ''; foreach ($services as $key => $title) { $settings = variable_get('uc_google_checkout_shipping_'. $key, array()); if ($settings['enable']) { $shipping_options .= ''; $shipping_options .= ''. $settings['default'] .''; $temp = explode('_', $key, 2); $shipping_options .= ''. $companies[$temp[0]] .''; $shipping_options .= ''. $settings['pickup'] .''; $shipping_options .= ''. $services[$key] .''; if ($settings['fixed_charge']) { $context = array( 'revision' => 'formatted-original', 'type' => 'amount', ); $options = array( 'sign' => FALSE, 'thou' => FALSE, 'dec' => '.', ); $shipping_options .= ''. uc_price($settings['fixed_charge'], $context, $options) .''; } if ($settings['percent_adjustment']) { $shipping_options .= ''. (float)$settings['percent_adjustment'] .''; } $shipping_options .= ''; } } if ($shipping_options) { $output .= ''; $output .= ''; $output .= ''; $output .= $shipping_options; $output .= ''; $address = variable_get('uc_quote_store_default_address', new stdClass()); if (empty($address)) { $address->city = variable_get('uc_store_city', NULL); $address->zone = uc_get_zone_code(variable_get('uc_store_zone', NULL)); $address->postal_code = variable_get('uc_store_postal_code', NULL); $address->country = uc_store_default_country(); } $country = uc_get_country_data(array('country_id' => $address->country)); $address->country_code = $country[0]['country_iso_code_2']; $output .= ''; $output .= ''; $output .= ''; $output .= ''. $address->city .''; $output .= ''. $address->zone .''; $output .= ''. $address->country_code .''; $output .= ''. $address->postal_code .''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; $output .= ''; } } $tax_table = ''; $result = db_query("SELECT zone, rate, tax_shipping FROM {uc_gc_taxes}"); while ($tax = db_fetch_object($result)) { $tax_table .= ''; if ($tax->tax_shipping) { $tax_table .= 'true'; } $tax_table .= ''. (float)$tax->rate .''; $tax_table .= ''; $tax_table .= ''; $tax_table .= ''. $tax->zone .''; $tax_table .= ''; $tax_table .= ''; $tax_table .= ''; } if ($tax_table) { $output .= ''; $output .= ''; $output .= ''; $output .= $tax_table; $output .= ''; $output .= ''; $output .= ''; } $output .= ''. url('cart', array('absolute' => TRUE)) .''; if (($page = variable_get('uc_continue_shopping_url', '')) != '') { $output .= ''. url($page, array('absolute' => TRUE)) .''; } $output .= '218752253180456'; $output .= ''; $output .= ''; $output .= ''; } return $output; } function uc_google_checkout_headers() { if (variable_get('uc_google_checkout_mode', 'checkout') == 'checkout') { $merchant_id = variable_get('uc_google_checkout_merchant_id', ''); $merchant_key = variable_get('uc_google_checkout_merchant_key', ''); } else { $merchant_id = variable_get('uc_google_checkout_test_merchant_id', ''); $merchant_key = variable_get('uc_google_checkout_test_merchant_key', ''); } $headers = array(); $authorization = $merchant_id .':'. $merchant_key; if ($authorization != ':') { $headers['Authorization'] = 'Basic '. base64_encode($authorization); } $headers['Content-Type'] = 'application/xml; charset=UTF-8'; $headers['Accept'] = 'application/xml; charset=UTF-8'; return $headers; } function uc_google_checkout_send_request($api, $request) { if (variable_get('uc_google_checkout_mode', 'checkout') == 'checkout') { $merchant_id = variable_get('uc_google_checkout_merchant_id', ''); $checkout_url = 'https://checkout.google.com'; } else { $merchant_id = variable_get('uc_google_checkout_test_merchant_id', ''); $checkout_url = 'https://sandbox.google.com/checkout'; } // Google's XML parser doesn't like named entities apparently. str_replace(array('&', '<', '>'), array('&', '<', '>'), $request); $response_obj = drupal_http_request($checkout_url .'/api/checkout/v2/'. $api .'/Merchant/'. $merchant_id, uc_google_checkout_headers(), 'POST', $request); if ($response_obj->error) { watchdog('google', '@error', array('@error' => $response_obj->error), WATCHDOG_ERROR); } $response = new SimpleXMLElement($response_obj->data); if ($response->getName() == 'error') { $error = (string) $response->{'error-message'}; drupal_set_message($error, 'error'); watchdog('google', '@error', array('@error' => $error), WATCHDOG_ERROR); return NULL; } /** * Ugly hack to work around PHP bug, details here: * http://bugs.php.net/bug.php?id=23220 * We strip out errors that look something like: * warning: fread() [function.fread]: SSL fatal protocol error in... * Copied from http://drupal.org/node/70915. */ $messages = drupal_set_message(); $errors = $messages['error']; $total = count($errors); for ($i = 0; $i <= $total; $i++) { if (strpos($errors[$i], 'SSL: fatal protocol error in')) { unset($_SESSION['messages']['error'][$i]); } } if (empty($_SESSION['messages']['error'])) { unset($_SESSION['messages']['error']); } db_query("DELETE FROM {watchdog} WHERE type = 'php' AND variables LIKE '%%SSL: fatal protocol error%%'"); // End of ugly hack. return $response; } function uc_google_checkout_pane_email_allowed($op, $arg1) { switch ($op) { case 'customer': case 'view': if ($arg1->data['email_allowed']) { $output = t('Customer will accept marketing emails.'); } else { $output = t('Customer does not want marketing emails.'); } return $output; } } /** * Add setting callbacks to the payment settings section * The fulfillment sections need coded still. JS. */ function uc_payment_method_google_checkout($op, &$arg1) { switch ($op) { case 'order-view': $output = l(t('Google Checkout terminal'), 'admin/store/orders/'. $arg1->order_id .'/google_checkout'); return $output; case 'settings': $form = array(); $form['link'] = array( '#value' => l(t('Click here to go to Google Checkout settings.'), 'admin/store/settings/google_checkout'), ); return $form; } } function uc_google_checkout_new_order($new_order) { $order_id = $new_order->{'shopping-cart'}->{'merchant-private-data'}->{'order-id'}; $cart_id = (string) $new_order->{'shopping-cart'}->{'merchant-private-data'}->{'cart-id'}; $order = uc_order_load($order_id); if ($order) { $shipping_address = $new_order->{'buyer-shipping-address'}; $order->delivery_company = $shipping_address->{'company-name'}; $order->delivery_first_name = $shipping_address->{'structured-name'}->{'first-name'}; $order->delivery_last_name = $shipping_address->{'structured-name'}->{'last-name'}; $order->delivery_phone = $shipping_address->phone; $order->delivery_street1 = $shipping_address->address1; $order->delivery_street2 = $shipping_address->address2; $order->delivery_city = $shipping_address->city; $zone_id = db_result(db_query("SELECT zone_id FROM {uc_zones} WHERE zone_code = '%s'", $shipping_address->region)); $order->delivery_zone = $zone_id; $countries = uc_get_country_data(array('country_iso_code_2' => $shipping_address->{'country-code'})); $order->delivery_country = $countries[0]['country_id']; $order->delivery_postal_code = $shipping_address->{'postal-code'}; $billing_address = $new_order->{'buyer-billing-address'}; $order->billing_company = $billing_address->{'company-name'}; $order->billing_first_name = $billing_address->{'structured-name'}->{'first-name'}; $order->billing_last_name = $billing_address->{'structured-name'}->{'last-name'}; $order->billing_phone = $billing_address->phone; $order->billing_street1 = $billing_address->address1; $order->billing_street2 = $billing_address->address2; $order->billing_city = $billing_address->city; if ($billing_address['region'] != $shipping_address->region) { $zone_id = db_result(db_query("SELECT zone_id FROM {uc_zones} WHERE zone_code = '%s'", $billing_address->region)); } $order->billing_zone = $zone_id; if ($billing_address->{'country-code'} != $shipping_address->{'country-code'}) { $countries = uc_get_country_data(array('country_iso_code_2' => $billing_address->{'country-code'})); } $order->billing_country = $countries[0]['country_id']; $order->billing_postal_code = $billing_address->{'postal-code'}; if (!$order->primary_email) { $order->primary_email = $billing_address->email; } if ($new_order->{'buyer-marketing-preferences'}->{'email-allowed'} == 'true') { $order->data['email_allowed'] = TRUE; if (module_exists('simplenews')) { simplenews_subscribe_user($order->primary_email, variable_get('uc_google_checkout_simplenews_tid', 0), TRUE); } } else { $order->data['email_allowed'] = FALSE; if (module_exists('simplenews')) { simplenews_unsubscribe_user($order->primary_email, variable_get('uc_google_checkout_simplenews_tid', 0), FALSE); } } $order->payment_method = 'google_checkout'; $comments = array(); uc_order_line_item_add($order_id, 'tax', t('Total tax'), $new_order->{'order-adjustment'}->{'total-tax'}); if (isset($new_order->{'order-adjustment'}->shipping)) { $shipping_line = $new_order->{'order-adjustment'}->shipping[0]; uc_order_line_item_add($order_id, 'shipping', check_plain($shipping_line->{'shipping-name'}), $shipping_line->{'shipping-cost'}); } if (isset($new_order->{'order-adjustment'}->{'merchant-codes'})) { foreach ($new_order->{'order-adjustment'}->{'merchant-codes'}->children() as $adjustment) { $type = $adjustment->getName(); if ($type == 'coupon-adjustment') { uc_order_line_item_add($order_id, 'gc_coupon', check_plain($adjustment->code), -$adjustment->{'applied-amount'}); $comments[] = check_plain($adjustment->message); } elseif ($type == 'gift-certificate-adjustment') { uc_order_line_item_add($order_id, 'gc_gift_certificate', check_plain($adjustment->code), -($adjustment->{'applied-amount'})); $comments[] = check_plain($adjustment->message); } } } uc_order_save($order); uc_cart_complete_sale($order); // uc_cart_complete_sale() empties the current cart (Google Checkout // API's cart) so we must empty the customer's manually. uc_cart_empty($cart_id); // Add a comment to let sales team know this came in through the site. uc_order_comment_save($order->order_id, 0, t('Order created through Google Checkout (#@gco_order).', array('@gco_order' => $new_order->{'google-order-number'})), 'admin'); // uc_cart_complete_sale() also unsets some $_SESSION variables. These // are tied to the user-id, so we record that for when they log in later. $users = variable_get('uc_google_checkout_order_users', array()); $users[$order->uid] = $order->uid; variable_set('uc_google_checkout_order_users', $users); // Add messages from order adjustments (coupons, gift certificates, etc.). foreach ($comments as $comment) { $comment = trim($comment); if ($comment) { uc_order_comment_save($order->order_id, 0, $comment, 'order', $order->order_status, 0); } } db_query("INSERT INTO {uc_gc_orders} (order_id, gc_order_number, gc_total) VALUES (%d, '%s', %f)", $order_id, $new_order->{'google-order-number'}, $new_order->{'order-total'}); uc_google_checkout_notification_acknowledgement($new_order['serial-number']); } else { uc_google_checkout_notification_error(); } } function uc_google_checkout_accept_risk($risk) { $order_id = uc_google_checkout_get_order($risk->{'google-order-number'}); if ($order_id) { $risk_info = $risk->{'risk-information'}; $assessment = t('Risk information notification:') .'
'; $avs_response = $risk_info->{'avs-response'}; switch ($avs_response) { case 'Y': $assessment .= t('- Full AVS match (address and postal code)'); break; case 'P': $assessment .= t('- Partial AVS match (postal code only)'); break; case 'A': $assessment .= t('- Partial AVS match (address only)'); break; case 'N': $assessment .= t('- No AVS match'); break; case 'U': $assessment .= t('- AVS not supported by issuer'); break; default: $assessment .= t('Error: No AVS response.'); break; } $assessment .= '
'; $cvn_response = $risk_info->{'cvn-response'}; switch ($cvn_response) { case 'M': $assessment .= t('- CVN match'); break; case 'N': $assessment .= t('- No CVN match'); break; case 'U': $assessment .= t('- CVN not available'); break; case 'E': $assessment .= t('- CVN error'); break; default: $assessment .= t('Error: No CVN response.'); break; } $assessment .= '
'; $assessment .= t('Partial CC number: %s', array('%s' => $risk_info->{'partial-cc-number'})); $assessment .= '
'; $assessment .= format_plural($risk_info->{'buyer-account-age'}, 'Google Checkout member for @count month.', 'Google Checkout member for @count months.'); $assessment .= '
'; $assessment .= t('Eligible for protection: @bool', array('@bool' => drupal_strtoupper($risk_info->{'eligible-for-protection'}))); uc_order_comment_save($order_id, 0, $assessment, 'admin', 'chargeable'); uc_google_checkout_notification_acknowledgement($risk['serial-number']); } } function uc_google_checkout_order_state_change($change) { $order_id = uc_google_checkout_get_order($change->{'google-order-number'}); if ($order_id) { $new_financial = (string) $change->{'new-financial-order-state'}; $new_fulfillment = (string) $change->{'new-fulfillment-order-state'}; $prev_financial = (string) $change->{'previous-financial-order-state'}; $prev_fulfillment = (string) $change->{'previous-fulfillment-order-state'}; db_query("UPDATE {uc_gc_orders} SET financial_state = '%s', fulfillment_state = '%s' WHERE order_id = %d AND financial_state = '%s' AND fulfillment_state = '%s'", array($new_financial, $new_fulfillment, $order_id, $prev_financial, $prev_fulfillment)); if ($new_financial != $prev_financial) { $_SESSION['google_updates'] = TRUE; switch ($new_financial) { case 'CHARGEABLE': uc_order_update_status($order_id, 'chargeable'); break; case 'CHARGING': watchdog('google', 'Charging @order_id', array('@order_id' => $order_id)); break; case 'CHARGED': watchdog('google', 'Charged @order_id', array('@order_id' => $order_id)); break; case 'PAYMENT_DECLINED': watchdog('google', 'Payment declined @order_id', array('@order_id' => $order_id)); break; case 'CANCELLED_BY_GOOGLE': $message = t('Order %order canceled by Google: %reason', array('%order' => $order_id, '%reason' => $change->reason)); uc_order_comment_save($order_id, 0, $message, 'admin', 'canceled'); case 'CANCELLED': uc_order_comment_save($order_id, 0, t('Order canceled.'), 'order', 'canceled'); uc_order_update_status($order_id, 'canceled'); break; default: break; } unset($_SESSION['google_updates']); } elseif ($new_fulfillment != $prev_fulfillment) { $_SESSION['google_updates'] = TRUE; switch ($new_fulfillment) { case 'PROCESSING': watchdog('google', 'Processing @order_id', array('@order_id' => $order_id)); break; case 'DELIVERED': uc_order_update_status($order_id, 'completed'); watchdog('google', 'Delivered @order_id', array('@order_id' => $order_id)); break; case 'WILL_NOT_DELIVER': watchdog('google', 'Will not deliver @order_id', array('@order_id' => $order_id)); break; } unset($_SESSION['google_updates']); } uc_google_checkout_notification_acknowledgement($change['serial-number']); } else { uc_google_checkout_notification_error(); } } function uc_google_checkout_charge($order_id, $amount) { $google_order_number = uc_google_checkout_get_google_number($order_id); $output = ''; $output .= ''; $output .= "\n"; $output .= ''; $output .= ''. $amount .''; $output .= ''; if ($response = uc_google_checkout_send_request('request', $output)) { drupal_set_message(t('Charge request sent to Google Checkout. The charge confirmation should appear on this page momentarily.')); } return 'admin/store/orders/'. $order_id; } function uc_google_checkout_charge_order($charge) { $order_id = uc_google_checkout_get_order($charge->{'google-order-number'}); if ($order_id) { $amount = (string) $charge->{'latest-charge-amount'}; uc_payment_enter($order_id, 'google_checkout', $amount, 0, '', t('Payment received by Google Checkout')); $context = array( 'revision' => 'formatted-original', 'type' => 'amount', ); uc_order_comment_save($order_id, 0, t('Payment of %amount received by Google Checkout.', array('%amount' => uc_price($amount, $context))), 'admin', 'chargeable'); uc_google_checkout_notification_acknowledgement($charge['serial-number']); } else { uc_google_checkout_notification_error(); } } function uc_google_checkout_refund($order_id, $amount, $reason, $comment = '') { $google_order_number = uc_google_checkout_get_google_number($order_id); $output = ''; $output .= ''; $output .= "\n"; $output .= ''; $output .= ''. $amount .''; $output .= ''. check_plain($comment) .''; $output .= ''. check_plain($reason) .''; $output .= ''; if ($response = uc_google_checkout_send_request('request', $output)) { drupal_set_message(t('Refund request sent to Google Checkout. The refund confirmation should appear on this page momentarily.')); } return 'admin/store/orders/'. $order_id; } function uc_google_checkout_refund_order($refund) { $order_id = uc_google_checkout_get_order($refund->{'google-order-number'}); if ($order_id) { uc_payment_enter($order_id, 'google_checkout', -$refund->{'latest-refund-amount'}, 0, '', t('Refund received by Google Checkout')); $context = array( 'revision' => 'formatted-original', 'type' => 'amount', ); uc_order_comment_save($order_id, 0, t('Refund of %amount received by Google Checkout.', array('%amount' => uc_price($refund->{'latest-refund-amount'}, $context))), 'admin', 'processing'); uc_google_checkout_notification_acknowledgement($refund['serial-number']); } else { uc_google_checkout_notification_error(); } } function uc_google_checkout_notify_update($form, &$form_state) { $order = uc_order_load($form_state['values']['order_id']); if ($order !== FALSE && $order->google_order_number && isset($form_state['values']['order_comment']) && drupal_strlen($form_state['values']['order_comment'])) { $request = uc_google_checkout_buyer_message_request($order->google_order_number, $form_state['values']['order_comment']); $response = uc_google_checkout_send_request('request', $request); } } function uc_google_checkout_buyer_message_request($google_order_number, $message) { $output = ''; $output .= "\n"; $output .= ''; $output .= ''. check_plain($message) .''; $output .= 'true'; $output .= ''; return $output; } function uc_google_checkout_cancel_order($order) { $request = ''; $request .= "\n"; $request .= ''; $request .= ''. token_replace_multiple(variable_get('uc_google_checkout_order_cancel_reason', t('Order canceled. See order comments at [order-url] for more information.')), array('global' => NULL, 'order' => $order)) .''; $request .= ''; if ($response = uc_google_checkout_send_request('request', $request)) { return TRUE; } else { return FALSE; } } function uc_google_checkout_notification_acknowledgement($serial_number) { drupal_set_header('HTTP/1.1 200 OK'); print ''; print "\n"; print ''; exit(); } function uc_google_checkout_notification_error($message = NULL) { if (is_null($message)) { $message = t('Unknown order id or malformed XML.'); } drupal_set_header('HTTP/1.1 400 Bad Request'); watchdog('google', '!message', array('!message' => $message), WATCHDOG_ERROR); exit(); } function uc_google_checkout_get_order($google_order_number) { return db_result(db_query("SELECT order_id FROM {uc_gc_orders} WHERE gc_order_number = '%s'", $google_order_number)); } function uc_google_checkout_get_google_number($order_id) { return db_result(db_query("SELECT gc_order_number FROM {uc_gc_orders} WHERE order_id = %d", $order_id)); } function uc_google_checkout_shipping_services() { return array_merge(uc_google_checkout_fedex_services(), uc_google_checkout_ups_services(), uc_google_checkout_usps_services()); } function uc_google_checkout_fedex_services() { return array( 'fedex_ground' => 'Ground', 'fedex_home' => 'Home Delivery', 'fedex_express' => 'Express Saver', 'fedex_first' => 'First Overnight', 'fedex_priority' => 'Priority Overnight', 'fedex_standard' => 'Standard Overnight', 'fedex_2day' => '2Day', ); } function uc_google_checkout_ups_services() { return array( 'ups_next_day' => 'Next Day Air', 'ups_next_day_am' => 'Next Day Air Early AM', 'ups_next_day_saver' => 'Next Day Air Saver', 'ups_2nd_day' => '2nd Day Air', 'ups_2nd_day_am' => '2nd Day Air AM', 'ups_3_day' => '3 Day Select', 'ups_ground' => 'Ground', ); } function uc_google_checkout_usps_services() { return array( 'usps_express' => 'Express Mail', 'usps_priority' => 'Priority Mail', 'usps_parcel' => 'Parcel Post', 'usps_media' => 'Media Mail', ); } function uc_google_checkout_shipping_companies() { return array( 'fedex' => 'FedEx', 'ups' => 'UPS', 'usps' => 'USPS', ); } /** * Returns an array of options for the currency selection widget. */ function _uc_google_checkout_currency_codes() { return drupal_map_assoc(array('AUD', 'CAD', 'EUR', 'GBP', 'HKD', 'JPY', 'USD')); }