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'));
}