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; } /** * Implements hook_menu(). */ 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'), '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' => TRUE, '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'), 'file' => 'uc_google_checkout.admin.inc', ); return $items; } /** * Menu title callback function. */ function uc_google_checkout_terminal_title($order) { return t('Google Checkout terminal: Order @order_id', array('@order_id' => $order->order_id)); } /** * Implements hook_init(). */ 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'; } /** * Implements hook_theme(). */ function uc_google_checkout_theme() { return array( 'uc_google_checkout_shipping_settings' => array( 'render element' => 'form', 'file' => 'uc_google_checkout.admin.inc', ), 'uc_google_checkout_taxes_settings' => array( 'render element' => 'form', 'file' => 'uc_google_checkout.admin.inc', ), ); } /** * Implements hook_form_alter(). */ 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['base']['gc_salable'] = array( '#type' => 'checkbox', '#title' => t('Product 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.', array('!url' => $policy_url)), '#weight' => 40, ); } } } /** * Implements hook_form_FORM_ID_alter() for uc_payment_methods_form(). */ function uc_google_checkout_form_uc_payment_methods_form_alter(&$form, &$form_state) { // 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; } /** * Implements hook_form_FORM_ID_alter() for uc_payment_by_order_form(). */ function uc_google_checkout_form_uc_payment_by_order_form_alter(&$form, &$form_state) { unset($form['payments']['new']['method']['#options']['google_checkout']); } /** * Implements hook_form_FORM_ID_alter() for uc_order_view_update_form(). */ function uc_google_checkout_form_uc_order_view_update_form_alter(&$form, &$form_state) { $form['#submit'][] = 'uc_google_checkout_notify_update'; } /** * Implements hook_form_FORM_ID_alter() for uc_store_format_settings_form(). */ function uc_google_checkout_form_uc_store_format_settings_form_alter(&$form, &$form_state) { $form['currency']['uc_currency_code']['#description'] .= ' ' . t('Google Checkout only accepts the following currencies: @list', array('@list' => implode(', ', _uc_google_checkout_currency_codes()))); } /** * Implements hook_node_insert(). */ function uc_google_checkout_node_insert($node) { uc_google_checkout_node_update($node); } /** * Implements hook_node_update(). */ function uc_google_checkout_node_update($node) { if (uc_product_is_product($node->type)) { if (isset($node->gc_salable)) { if (!$node->revision) { db_delete('uc_gc_products') ->condition('vid', $node->vid) ->execute(); } db_insert('uc_gc_products') ->fields(array( 'vid' => $node->vid, 'nid' => $node->nid, 'gc_salable' => $node->gc_salable, )) ->execute(); } } } /** * Implements hook_node_load(). */ function uc_google_checkout_node_load($nodes, $types) { $vids = array(); $product_types = uc_product_types(); foreach ($nodes as &$node) { if (in_array($node->type, $product_types)) { $vids[$node->nid] = $node->vid; // Set default value. $node->gc_salable = TRUE; } } if ($vids) { $result = db_query("SELECT nid, gc_salable FROM {uc_gc_products} WHERE vid IN (:vids)", array(':vids' => $vids)); foreach ($result as $salable) { $nodes[$node->nid]->gc_salable = $salable->gc_salable; } } } /** * Implements hook_node_delete(). */ function uc_google_checkout_node_delete($node) { db_delete('uc_gc_products') ->condition('nid', $node->nid) ->execute(); } /** * Implements hook_node_revision_delete(). */ function uc_google_checkout_node_revision_delete($node) { db_delete('uc_gc_products') ->condition('vid', $node->vid) ->execute(); } /****************************************************************************** * Hook Functions (Ubercart) * ******************************************************************************/ /** * Implements hook_uc_cart_pane(). */ function uc_google_checkout_uc_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') + array( '#prefix' => '
', '#suffix' => '
', ), ); return $panes; } /** * Implements hook_uc_order_pane(). */ function uc_google_checkout_uc_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; } /** * Implements hook_uc_line_item(). */ function uc_google_checkout_uc_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; } /** * Implements hook_uc_order(). */ function uc_google_checkout_uc_order($op, &$order, $arg2) { switch ($op) { case 'load': $result = db_query("SELECT * FROM {uc_gc_orders} WHERE order_id = :id", array(':id' => $order->order_id)); if ($gc = $result->fetchObject()) { $order->google_order_number = $gc->gc_order_number; $order->financial_state = $gc->financial_state; $order->fulfillment_state = $gc->fulfillment_state; $order->gc_total = $gc->gc_total; } break; case 'can_update': if (!isset($order->google_order_number) || isset($_SESSION['google_updates']) && $_SESSION['google_updates']) { return TRUE; } switch ($arg2) { case 'canceled': if (uc_google_checkout_cancel_order($order)) { 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; } } /** * Implements hook_uc_payment_method(). */ function uc_google_checkout_uc_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; } /** * Implements hook_uc_payment_gateway(). */ function uc_google_checkout_uc_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; } /** * Implements hook_uc_shipment(). */ function uc_google_checkout_uc_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 * ******************************************************************************/ /** * Form builder for uc_google_checkout_cart_form(). * * @see uc_google_checkout_cart_form_submit() * @ingroup forms */ function uc_google_checkout_cart_form($form, &$form_state) { 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; } $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'] = array( '#type' => 'image_button', '#src' => $checkout_url . '/buttons/checkout.gif?merchant_id=' . $merchant_id . '&w=' . $width . '&h=' . $height . '&style=' . variable_get('uc_google_checkout_button_color', 'trans') . '&variant=' . ($disable ? 'disabled' : 'text') . '&loc=en_US', '#disabled' => $disable, '#attributes' => array( 'alt' => t('Google Checkout'), 'title' => t('Fast checkout through Google.'), 'height' => $height, 'width' => $width, ), '#description' => '' . t('What is Google Checkout?') . '', ); return $form; } /** * Form submission handler for uc_google_checkout_cart_form(). * * @see uc_google_checkout_cart_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']) { $shipping_options .= '' . uc_currency_format($settings['fixed_charge'], FALSE, FALSE, '.') . ''; } 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'); if (empty($address)) { $address = new UcAddress(); $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}"); foreach ($result as $tax) { $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'; } if (!$merchant_id) { return; } // 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, array( 'headers' => uc_google_checkout_headers(), 'method' => 'POST', 'data' => $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_delete('watchdog') ->condition('type', 'php') ->condition('variables', '%SSL: fatal protocol error%', 'LIKE') ->execute(); // End of ugly hack. return $response; } function uc_google_checkout_pane_email_allowed($op, $order) { switch ($op) { case 'customer': case 'view': if (isset($order->data['email_allowed']) && $order->data['email_allowed']) { $build = array('#markup' => t('Customer will accept marketing emails.')); } else { $build = array('#markup' => t('Customer does not want marketing emails.')); } return $build; } } /** * Adds setting callbacks to the payment settings section * The fulfillment sections need coded still. JS. */ function uc_payment_method_google_checkout($op, &$order) { switch ($op) { case 'order-view': $build['#markup'] = l(t('Google Checkout terminal'), 'admin/store/orders/' . $order->order_id . '/google_checkout'); return $build; case 'settings': $form = array(); $form['link'] = array( '#markup' => 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_query("SELECT zone_id FROM {uc_zones} WHERE zone_code = :code", array(':code' => $shipping_address->region))->fetchField(); $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_query("SELECT zone_id FROM {uc_zones} WHERE zone_code = :code", array(':code' => $billing_address->region))->fetchField(); } $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_insert('uc_gc_orders') ->fields(array( 'order_id' => $order_id, 'gc_order_number' => $new_order->{'google-order-number'}, 'gc_total' => $new_order->{'order-total'}, )) ->execute(); 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 1 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_update('uc_gc_orders') ->fields(array( 'financial_state' => $new_financial, 'fulfillment_state' => $new_fulfillment, )) ->condition('order_id', $order_id) ->condition('financial_state', $prev_financial) ->condition('fulfillment_state', $prev_fulfillment) ->execute(); 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')); uc_order_comment_save($order_id, 0, t('Payment of %amount received by Google Checkout.', array('%amount' => uc_currency_format($amount))), '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')); uc_order_comment_save($order_id, 0, t('Refund of %amount received by Google Checkout.', array('%amount' => uc_currency_format($refund->{'latest-refund-amount'}))), '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 && isset($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(variable_get('uc_google_checkout_order_cancel_reason', t('Order canceled. See order comments at [uc_order:url] for more information.')), array('uc_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('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('400 Bad Request'); watchdog('google', '!message', array('!message' => $message), WATCHDOG_ERROR); exit(); } function uc_google_checkout_get_order($google_order_number) { return db_query("SELECT order_id FROM {uc_gc_orders} WHERE gc_order_number = :number", array(':number' => $google_order_number))->fetchField(); } function uc_google_checkout_get_google_number($order_id) { return db_query("SELECT gc_order_number FROM {uc_gc_orders} WHERE order_id = :id", array(':id' => $order_id))->fetchField(); } 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')); }