Index: README.txt
=========================================================
--- README.txt	(revision 1.1.2.1)
+++ README.txt	Working Copy
@@ -3,7 +3,7 @@
 ********************************************************************
 Name: Quickbooks Ubercart Integration
 Author: Sarva Bryant <sarva at aliandesign dot com>
-Drupal: 5.0.x
+Drupal: 6.x
 ********************************************************************
 DESCRIPTION:

@@ -46,10 +46,10 @@
 3. Install the Quickbooks API, Web Connector, and this module.

 4. Setup Web Connector settings
-   http://yoursite.com/admin/settings/qb/qbwc
+   http://yoursite.com/admin/settings/qb

 5. Download the Web Connector Configuration file
-   http://yoursite.com/admin/settings/qb/qbw
+   http://yoursite.com/admin/settings/qb/qwc

 6. Setup Ubercart Quickbook settings if needed
    http://yoursite.com/admin/store/settings/qb
Index: uc_qb.info
=========================================================
--- uc_qb.info	(revision 1.1.2.1)
+++ uc_qb.info	Working Copy
@@ -1,4 +1,6 @@
 name = QuickBooks Ubercart Integration
 description = Uses QuickBooks Web Connector to send and receive Ubercart data to/from QuickBooks
-dependencies = qbwc uc_store
-core = ubercart
+dependencies[] = qbwc
+dependencies[] = uc_store
+core = 6.x
+php = 5
Index: uc_qb.module
=========================================================
--- uc_qb.module	(revision 1.1.2.1)
+++ uc_qb.module	Working Copy
@@ -6,35 +6,31 @@
  *
  * 1. Advanced/separated error system (using QBWC interactive error handling)
  * 2. Import product data from QuickBooks
- * 3. **Important** Update customer email addresses in QuickBooks when the user changes them
+ * 3. **Important** Update customer email addresses in QuickBooks when the user changes them
  */

 /**
  *  Implementation of hook_menu()
  */
-function uc_qb_menu($may_cache = false) {
+function uc_qb_menu() {
   $items = array();

-  if ($may_cache) {
-  	$items[] = array(
-      'path' => 'admin/store/settings/qb',
-      'title' => t('QB import/export'),
-      'description' => t('Import/Export store data to QuickBooks using Web Connector'),
-      'callback' => 'drupal_get_form',
-      'callback arguments' => array('uc_qb_settings'),
-      'access' => user_access('administer quickbooks import/export'),
+  $items['admin/store/settings/qb'] = array(
+    'title' => 'QB import/export',
+    'description' => 'Import/Export store data to QuickBooks using Web Connector',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('uc_qb_settings'),
+    'access arguments' => array('administer quickbooks import/export'),
-      'type' => MENU_NORMAL_ITEM,
-    );
-    // TODO: Write help page that also can display the latest errors
+    'type' => MENU_NORMAL_ITEM,
+  );
+  // TODO: Write help page that also can display the latest errors
-    $items[] = array(
-      'path' => 'admin/store/settings/qb/help',
-      'title' => t('QuickBooks Import/Export Help'),
-      'description' => t('Detailed information for importing and exporting to QuickBooks using the Web Connector.'),
-      'callback' => 'uc_qb_admin_help',
-      'access' => user_access('administer quickbooks import/export'),
+  $items['admin/store/settings/qb/help'] = array(
+    'title' => 'QuickBooks Import/Export Help',
+    'description' => 'Detailed information for importing and exporting to QuickBooks using the Web Connector.',
+    'page callback' => 'uc_qb_admin_help',
+    'access arguments' => array('administer quickbooks import/export'),
-      'type' => MENU_CALLBACK,
-    );
+    'type' => MENU_CALLBACK,
+  );
-  }

   return $items;
 }
@@ -43,7 +39,7 @@
  * Menu callback for settings related to QB import
  */
 function uc_qb_settings() {
-	$form = array();
+  $form = array();

   $form['uc_qb_start_order'] = array(
     '#type' => 'textfield',
@@ -68,24 +64,16 @@
   return array('administer quickbooks import/export');
 }

-/**
- * Implementation of hook_qbwc_authenticate()
- */
-function uc_qb_qbwc_authenticate($ticket, $user) {
-	  // Make sure this is defined and set to an array to avoid errors
-  if (!is_array($_SESSION['qb_orders'])) {
-    $_SESSION['qb_orders'] = array();
-  }
+function uc_qb_fetch_orders() {
+  $qb_orders = array();

   // Only deal with orders for now. Everything required to make a valid order in quickbooks will
   // be exported, but nothing else (won't export customers/products without either of those being part of a purchase)
   $last_export = variable_get('uc_qb_last_export', 0);

   // Get a list of orders needing exported
-  $result = db_query('SELECT DISTINCT(uop.order_id), uc.uid, uc.modified, uc.order_total, uc.primary_email, uc.order_status, uc.data as order_data, u.name, u.data as user_data FROM {uc_orders} uc INNER JOIN {users} u ON uc.uid = u.uid LEFT JOIN {uc_order_products} uop ON uc.order_id = uop.order_id WHERE uc.modified > "%d" AND order_status IN ("completed", "payment_received") AND uop.nid IS NOT NULL AND uc.order_id >= "%d" ORDER BY uc.modified ASC', $last_export, variable_get('uc_qb_start_order', 0));
-
-  $_SESSION['qb_orders_count'] = db_num_rows($result);
-  $_SESSION['qb_orders_done'] = 0;
+  $result = db_query('SELECT DISTINCT(uop.order_id), uc.uid, uc.modified, uc.order_total, uc.primary_email, uc.order_status, uc.data as order_data, u.name, u.data as user_data FROM {uc_orders} uc INNER JOIN {users} u ON uc.uid = u.uid LEFT JOIN {uc_order_products} uop ON uc.order_id = uop.order_id WHERE uc.modified > %d AND order_status IN ("completed", "payment_received") AND uop.nid IS NOT NULL AND uc.order_id >= %d ORDER BY uc.modified ASC', $last_export, variable_get('uc_qb_start_order', 0));
+  $count = db_result(db_query('SELECT COUNT(DISTINCT(uop.order_id)) FROM {uc_orders} uc INNER JOIN {users} u ON uc.uid = u.uid LEFT JOIN {uc_order_products} uop ON uc.order_id = uop.order_id WHERE uc.modified > %d AND order_status IN ("completed", "payment_received") AND uop.nid IS NOT NULL AND uc.order_id >= %d', $last_export, variable_get('uc_qb_start_order', 0)));

   while ($item = db_fetch_object($result)) {
     $item->user_data = $item->uid ? unserialize($item->user_data) : array();
@@ -93,26 +81,32 @@

     if ($item->order_data['QBProcessed']) {
       // This item has already been processed
-      $_SESSION['qb_orders_count']--;
       continue;
     }

     // Save the orders in the session so we don't have to run the query again
-    $_SESSION['qb_orders'][$item->order_id] = $item;
+    $qb_orders[$item->order_id] = $item;
   }

-  // Return true if orders need processing signaling we have work for QB
-  if (!empty($_SESSION['qb_orders'])) {
-  	return true;
-  }
+  qbwc_set('orders', $qb_orders);
+
+  return $qb_orders;
 }

 /**
  * Implementation of hook_qbwc_response()
- *
+ *
  * @Description: Receive queries for QB data and set appropriate session variables for use in hook_qbwc_request()
  */
-function uc_qb_qbwc_response($response, $hresult, $message, $saved) {
+function uc_qb_qbwc_response($response = array(), $hresult = array(), $saved, $message) {
+  watchdog('uc_qb', dpr($response, TRUE, 'response'), NULL, WATCHDOG_DEBUG);
+  watchdog('uc_qb', dpr($hresult, TRUE, 'hresult (data?)'), NULL, WATCHDOG_DEBUG);
+  watchdog('uc_qb', dpr($saved, TRUE, 'saved'), NULL, WATCHDOG_DEBUG);
+  watchdog('uc_qb', dpr($message, TRUE, 'message'), NULL, WATCHDOG_DEBUG);
+
+  return 100;
+
+
   $done = &$_SESSION['qb_orders_done'];
   $new = array();
   // Go through the responses, dealing with each in turn
@@ -121,483 +115,530 @@
     $returnCnt = $element->getAttribute('retCount');
     $statusCode = $element->getAttribute('statusCode');
     $statusMessage = $element->getAttribute('statusMessage');
-
+
     if ($statusCode > 0) {
-    	watchdog('uc_qb', t('QB responded to a request with error #%code (%message)', array('%code' => $statusCode, '%message' => $statusMessage)), WATCHDOG_ERROR);
+      watchdog('uc_qb', 'QB responded to a request with error #%code (%message)', array('%code' => $statusCode, '%message' => $statusMessage), WATCHDOG_ERROR);
     }
     if ($statusCode == 3231) {
       // This element was not processed, so skip it
-    	continue;
+      continue;
     }

-    switch($element->tagName) {
-      // Check if the checked shipping method is available or not, and if not queries it to be created
-      case 'ShipMethodAddRs':
-        if (!isset($saved[$requestId])) {
-          $error = true;
-          break;
+  }
+
+  // Stop processing on errors
+  if ($error) {
+    return -1;
-        }
+  }

-        if ($statusCode == 0) {
-        	$_SESSION['qb_shipping_methods'][$saved[$requestId]['method']] = true;
+  if (!empty($new)) {
+    $_SESSION['qb_pending_requests'][] = $new;
-        }
+  }
-        else {
-        	$error = true;
-          break;
+
+  if ($_SESSION['qb_orders_count'] == 0) {
+    return 100;
-        }
+  }
-      break;
-    	case 'ShipMethodQueryRs':
-        if (!isset($saved[$requestId])) {
-          $error = true;
-          break;
+
+  return ($done / $_SESSION['qb_orders_count']) * 100;
+}
+
+// Check if the checked shipping method is available or not, and if not queries it to be created
+// case 'ShipMethodAddRs':
+function uc_qb_response_ship_method_add($response, $data, $status, $message) {
+  if ($status == 0) {
+    $shipping_methods = variable_get('uc_qb_shipping_methods', array());
+    $shipping_methods[$data['method']] = TRUE;
+    variable_set('uc_qb_shipping_methods', $shipping_methods);
-        }
+  }
+  watchdog('session', dpr($_SESSION, TRUE, 'ShipMethodAddRs'), NULL, WATCHDOG_DEBUG);
+}

-        if ($returnCnt > 0) {
-        	$_SESSION['qb_shipping_methods'][$saved[$requestId]['method']] = true;
+// case 'ShipMethodQueryRs':
+function uc_qb_response_ship_method_query($response, $data, $status, $message) {
+  if ($response['_retCount'] > 0) {
+    $shipping_methods = variable_get('uc_qb_shipping_methods', array());
+    $shipping_methods[$data['method']] = TRUE;
+    variable_set('uc_qb_shipping_methods', $shipping_methods);
-        }
-        else {
+  }
+  else {
-        	$new[] = array(
+    $request = array(
-            'name' => 'ShipMethodAddRq',
+      'name' => 'ShipMethodAddRq',
-            'request' => array('ShipMethodAdd' => array(
-              'Name' => $saved[$requestId]['method'],
+      'request' => array(
+        'ShipMethodAdd' => array(
+          'Name' => $data['method'],
-              'IsActive' => 'true'
+          'IsActive' => 'true'
-            )),
-            'data' => $saved[$requestId]
+        ),
+      ),
+      'data' => $data,
+      'callback' => array('uc_qb_response_ship_method_add'),
-          );
+    );
+    qbwc_request_queue($request);
-        }
+  }
-      break;
-      case 'ItemServiceAddRs':
-        if (!isset($saved[$requestId])) {
-          $error = true;
-          break;
-        }
+  watchdog('session', dpr($_SESSION, TRUE, 'ShipMethodQueryRs'), NULL, WATCHDOG_DEBUG);
+}

-        if ($statusCode == 0) {
-        	$_SESSION['qb_services'][$saved[$requestId]] = true;
-        }
-        else {
-        	$error = true;
-          break;
+// case 'ItemServiceAddRs':
+function uc_qb_response_item_service_add($response, $data, $status, $message) {
+  if ($status == 0) {
+    $services = variable_get('uc_qb_services', array());
+    $services[$data] = TRUE;
+    variable_set('uc_qb_services', $services);
-        }
+  }
-      break;
-      // Check if the SHIPPING service is available and create if necessary
-      case 'ItemServiceQueryRs':
-        if (!isset($saved[$requestId])) {
-          $error = true;
-          break;
-        }
+  watchdog('session', dpr($_SESSION, TRUE, 'ItemServiceAddRs'), NULL, WATCHDOG_DEBUG);
+}

-        if ($returnCnt > 0) {
-          $_SESSION['qb_services'][$saved[$requestId]] = true;
+// Check if the SHIPPING service is available and create if necessary
+// case 'ItemServiceQueryRs':
+function uc_qb_response_item_service_query($response, $data, $status, $message) {
+  if ($response['_retCount'] > 0) {
+    $services = variable_get('uc_qb_services', array());
+    $services[$data] = TRUE;
+    variable_set('uc_qb_services', $services);
-        }
-        else {
+  }
+  else {
-          $new[] = array(
+    $request = array(
-            'name' => 'ItemServiceAddRq',
+      'name' => 'ItemServiceAddRq',
-            'request' => array('ItemServiceAdd' => array(
-              'Name' => $saved[$requestId],
+      'request' => array(
+        'ItemServiceAdd' => array(
+          'Name' => $data,
-              'IsActive' => 'true',
-              'SalesOrPurchase' => array(
-                'Price' => '0.0',
-                'AccountRef' => array(
+          'IsActive' => 'true',
+          'SalesOrPurchase' => array(
+            'Price' => '0.0',
+            'AccountRef' => array(
-                  'FullName' => variable_get('uc_qb_service_account_'. $saved[$requestId], variable_get('uc_qb_service_account', 'Merchandise Sales'))
+              'FullName' => variable_get('uc_qb_service_account_'. $data, variable_get('uc_qb_service_account', 'Merchandise Sales')),
-                )
-              )
+            )
+          )
-            )),
-            'data' => $saved[$requestId]
+        ),
+      ),
+      'data' => $data,
+      'callback' => array('uc_qb_response_item_service_add'),
-          );
+    );
+    qbwc_request_queue($request);
-        }
+  }
-      break;
-      case 'PaymentMethodAddRs':
-        if (!isset($saved[$requestId])) {
-          $error = true;
-          break;
-        }
+  watchdog('session', dpr($_SESSION, TRUE, 'ItemServiceQueryRs'), NULL, WATCHDOG_DEBUG);
+}

+// case 'PaymentMethodAddRs':
+function uc_qb_response_payment_method_add($response, $data, $status, $message) {
-        // Check if the checked payment method is available or not, and if not queries it to be created
+  // Check if the checked payment method is available or not, and if not queries it to be created
-        if ($statusCode == 0) {
-          $_SESSION['qb_payment_methods'][$saved[$requestId]] = true;
+  if ($status == 0) {
+    $payment_methods = variable_get('uc_qb_payment_methods', array());
+    $payment_methods[$data] = TRUE;
+    variable_set('uc_qb_payment_methods', $payment_methods);
-        }
+  }
-        else {
-          $error = true;
-          break;
-        }
-      break;
-      case 'PaymentMethodQueryRs':
-        if (!isset($saved[$requestId])) {
-          $error = true;
-          break;
-        }
+  watchdog('session', dpr($_SESSION, TRUE, 'PaymentMethodAddRs'), NULL, WATCHDOG_DEBUG);
+}

+// case 'PaymentMethodQueryRs':
+function uc_qb_response_payment_method_query($response, $data, $status, $message) {
-      // Check if the checked payment method is available or not, and if not queries it to be created
+  // Check if the checked payment method is available or not, and if not queries it to be created
-        if ($returnCnt > 0) {
-          $_SESSION['qb_payment_methods'][$saved[$requestId]] = true;
+  if ($response['_retCount'] > 0) {
+    $payment_methods = variable_get('uc_qb_payment_methods', array());
+    $payment_methods[$data] = TRUE;
+    variable_set('uc_qb_payment_methods', $payment_methods);
-        }
-        else {
+  }
+  else {
-          $new[] = array(
+    $request = array(
-            'name' => 'PaymentMethodAddRq',
+      'name' => 'PaymentMethodAddRq',
-            'request' => array('PaymentMethodAdd' => array(
-              'Name' => $saved[$requestId],
+      'request' => array(
+        'PaymentMethodAdd' => array(
+          'Name' => $data,
-              'IsActive' => 'true'
+          'IsActive' => 'true'
-            )),
-            'data' => $saved[$requestId]
+        ),
+      ),
+      'data' => $data,
+      'callback' => array('uc_qb_response_payment_method_add'),
-          );
+    );
+    qbwc_request_queue($request);
-        }
+  }
-      break;
-      // Check if the checked tax name is available or not, and if not queries it to be created
-      case 'ItemSalesTaxQueryRs':
-        if (!isset($saved[$requestId])) {
-          $error = true;
-          break;
-        }
+  watchdog('session', dpr($_SESSION, TRUE, 'PaymentMethodQueryRs'), NULL, WATCHDOG_DEBUG);
+}

-        if ($returnCnt > 0) {
-          $_SESSION['qb_tax_types'][$saved[$requestId]->type] = true;
+// Check if the checked tax name is available or not, and if not queries it to be created
+// case 'ItemSalesTaxQueryRs':
+function uc_qb_response_item_sales_tax_query($response, $data, $status, $message) {
+  if ($response['_retCount'] > 0) {
+    $tax_types = variable_get('uc_qb_tax_types', array());
+    $tax_types[$data->type] = TRUE;
+    variable_set('uc_qb_tax_types', $tax_types);
-        }
-        else {
+  }
+  else {
-          $new[] = array(
+    $request = array(
-            'name' => 'ItemSalesTaxAddRq',
+      'name' => 'ItemSalesTaxAddRq',
-            'request' => array('ItemSalesTaxAdd' => array(
-              'Name' => $saved[$requestId]->type,
+      'request' => array(
+        'ItemSalesTaxAdd' => array(
+          'Name' => $data->type,
-              'IsActive' => 'true'
+          'IsActive' => 'true'
-            ))
+        ),
+      ),
+      'data' => $data,
-          );
+    );
-        }
-      break;
-      // Check if the checked customers are available or not, and if not queries them to be created
-      case 'CustomerQueryRs':
-      case 'CustomerAddRs':
-        if (!isset($saved[$requestId])) {
-          $error = true;
-          break;
+    qbwc_request_queue($request);
-        }
+  }
+  watchdog('session', dpr($_SESSION, TRUE, 'ItemSalesTaxQueryRs'), NULL, WATCHDOG_DEBUG);
+}

-        $data = &$_SESSION['qb_orders'][$saved[$requestId]->order_id];
-        $data->qb_user_id_pending = false;
-        if ($statusCode == 0 && $user_id = $element->getElementsByTagName('ListID')->item(0)->nodeValue) {
-          $data->qb_user_id = $user_id;
-          if ($data->uid) {
-            $data->user_data['QBListID'] = $user_id;
-            db_query('UPDATE {users} SET data = "%s" WHERE uid = "%d"', serialize($data->user_data), $data->uid);
+// Check if the checked customers are available or not, and if not queries them to be created
+// case 'CustomerQueryRs':
+function uc_qb_response_customer_query($response, $data, $status, $message) {
+  uc_qb_response_customer_add($response, $data, $status, $message);
+}
+
+// case 'CustomerAddRs':
+function uc_qb_response_customer_add($response, $data, $status, $message) {
+  watchdog('uc_qb', dpr($response, TRUE, 'customer_add'), NULL, WATCHDOG_DEBUG);
+  $orders = qbwc_get('orders');
+  $order = &$orders[$data->order_id];
+  $order->qb_user_id_pending = FALSE;
+  if ($status == 0 && $user_id = $response[0]['ListID']) {
+    $order->qb_user_id = $user_id;
+    if ($order->uid) {
+      $order->user_data['QBListID'] = $user_id;
+      db_query('UPDATE {users} SET data = "%s" WHERE uid = %d', serialize($order->user_data), $order->uid);
-          }
-          else {
+    }
+    else {
-            $data->order_data['QBListID'] = $user_id;
-            db_query('UPDATE {uc_orders} SET data = "%s" WHERE order_id = "%d"', serialize($data->order_data), $data->order_id);
+      $order->order_data['QBListID'] = $user_id;
+      db_query('UPDATE {uc_orders} SET data = "%s" WHERE order_id = %d', serialize($order->order_data), $order->order_id);
-          }
-        }
-        // If this is an anonymous user and already exists, get the ListID for it, any other situation should not happen and is an error
+    }
+  }
+  // If this is an anonymous user and already exists, get the ListID for it, any other situation should not happen and is an error
-        else if ($data->uid == 0 && $statusCode == 3100) {
-        	$new[] = array(
+  else if ($status == 3100) {
+    $request = array(
-              'name' => 'CustomerQueryRq',
-              'request' => array(
+      'name' => 'CustomerQueryRq',
+      'request' => array(
-                'FullName' => $data->primary_email,
-                'IncludeRetElement' => 'ListID'
+        'FullName' => $order->uid ? $order->name : $order->primary_email,
+        'IncludeRetElement' => 'ListID',
-              ),
+      ),
-              'data' => $saved[$requestId]
+      'data' => $data,
+      'callback' => array('uc_qb_response_customer_query'),
-            );
+    );
+    qbwc_request_queue($request);
-        }
-        else {
-          // This should never happen. If it does, make a log entry for this order saying that it failed to get exported
+  }
+  else {
+    // This should never happen. If it does, make a log entry for this order saying that it failed to get exported
-          watchdog('uc_qb', t('Order #%order_id (and possibly others from this user) failed to get exported to QB because the user failed to get exported with status code #%code (%message).', array('%code' => $statusCode, '%order_id' => $data->order_id, '%message' => $statusMessage)), WATCHDOG_ERROR);
+    watchdog('uc_qb', 'Order #%order_id (and possibly others from this user) failed to get exported to QB because the user failed to get exported with status code #%code (%message).', array('%code' => $status, '%order_id' => $order->order_id, '%message' => $status), WATCHDOG_ERROR);
-        }
+  }
-      break;
-      // Response to adding a receipt
-      case 'SalesReceiptAddRs':
-        $error = true;
-        $data = &$_SESSION['qb_orders'][$saved[$requestId]->order_id];
-        $data->order_data['QBProcessed'] =  true;
-        $total = $element->getElementsByTagName('TotalAmount')->item(0)->nodeValue;
-        if ($statusCode == 0 && round($total, 2) == round($data->order_total, 2)) {
-          db_query('UPDATE {uc_orders} SET data = "%s" WHERE order_id = "%d"', serialize($data->order_data), $data->order_id);
-          variable_set('uc_qb_last_export', $data->modified);
+  qbwc_set('orders', $orders);
+  watchdog('session', dpr($_SESSION, TRUE, 'CustomerAddRs'), NULL, WATCHDOG_DEBUG);
+}
+
+// Response to adding a receipt
+// case 'SalesReceiptAddRs':
+function uc_qb_response_sales_receipt_add($response, $data, $status, $message) {
+  $orders = qbwc_get('orders');
+  $order = &$orders[$data->order_id];
+  $order->order_data['QBProcessed'] =  TRUE;
+  $total = $response[0]['TotalAmount'];
+  if ($status == 0 && round($total, 2) == round($order->order_total, 2)) {
+    db_query('UPDATE {uc_orders} SET data = "%s" WHERE order_id = %d', serialize($order->order_data), $order->order_id);
+    variable_set('uc_qb_last_export', $order->modified);
-          $done++;
-        }
-        // The amount recorded in QB does not match the right amount for some reason
+    $done++;
+  }
+  // The amount recorded in QB does not match the right amount for some reason
-        else if ($statusCode == 0) {
-          $_SESSION['qb_failed_orders'][] = $saved[$requestId];
-          watchdog('uc_qb', t('Order #%order exported successfully, but the sales receipt total did not match the correct total', array('%order' => $saved[$requestId]->order_id, '%code' => $statusCode, '%message' => $statusMessage)), WATCHDOG_ERROR);
+  else if ($status == 0) {
+    $failed_orders = qbwc_get('failed_orders');
+    $failed_orders[] = $data;
+    qbwc_set('failed_orders', $failed_orders);
+    watchdog('uc_qb', 'Order #%order exported successfully, but the sales receipt total did not match the correct total', array('%order' => $data->order_id, '%code' => $status, '%message' => $message), WATCHDOG_ERROR);

-          // Make the receipt pending so that it does not get processed fully before somebody takes a look at it
+    // Make the receipt pending so that it does not get processed fully before somebody takes a look at it
-          $new[] = array(
+    $request = array(
-            'name' => 'SalesReceiptModRq',
-            'request' => array(
+      'name' => 'SalesReceiptModRq',
+      'request' => array(
-              'TxnID' => $element->getElementsByTagName('TxnID')->item(0)->nodeValue,
-              'EditSequence' => $element->getElementsByTagName('EditSequence')->item(0)->nodeValue,
+        'TxnID' => $response[0]['TxnID'],
+        'EditSequence' => $response[0]['EditSequence'],
-              'IsPending' => 'true'
-            ),
+        'IsPending' => 'true'
+      ),
-            'data' => $saved[$requestId]
+      'data' => $data,
+      'callback' => array('uc_qb_response_sales_receipt_mod'),
-          );
+    );
+    qbwc_request_queue($request);
-        }
-        else {
+  }
+  else {
-        	$_SESSION['qb_failed_orders'][] = $saved[$requestId];
-          $_SESSION['qb_orders_count']--;
-          watchdog('uc_qb', t('Failed to export the order #%order with error code %code (%message) to QB', array('%order' => $saved[$requestId]->order_id, '%code' => $statusCode, '%message' => $statusMessage)), WATCHDOG_ERROR);
+    $failed_orders = qbwc_get('failed_orders');
+    $failed_orders[] = $data;
+    qbwc_set('failed_orders', $failed_orders);
+
+    watchdog('uc_qb', 'Failed to export the order #%order with error code %code (%message) to QB', array('%order' => $data->order_id, '%code' => $status, '%message' => $message), WATCHDOG_ERROR);
-        }
+  }
-      break;
-      case 'SalesReceiptModRs':
-        //Successfully changed the receipt to pending. Mark this as done.
-        if ($statusCode == 0) {
-        	$_SESSION['qb_orders_count']--;
+  qbwc_set('orders', $orders);
+  watchdog('session', dpr($_SESSION, TRUE, 'SalesReceiptAddRs'), NULL, WATCHDOG_DEBUG);
+}
+
+// case 'SalesReceiptModRs':
+function uc_qb_response_sales_receipt_mod($response, $data, $status, $message) {
+  if ($status != 0) {
+    watchdog('uc_qb', 'Failed to change the order #%order with error code %code (%message) in QB', array('%order' => $data->order_id, '%code' => $status, '%message' => $message), WATCHDOG_ERROR);
-        }
+  }
-        else {
-          watchdog('uc_qb', t('Failed to change the ', array('%order' => $saved[$requestId]->order_id, '%code' => $statusCode, '%message' => $statusMessage)), WATCHDOG_ERROR);
-        }
-      break;
-      // Response to a product search query
-      case 'ItemInventoryQueryRs':
-        $product = $saved[$requestId];
-        if ($returnCnt > 0) {
-          $model = $element->getElementsByTagName('Name')->item(0)->nodeValue;
-          $id = $element->getElementsByTagName('ListID')->item(0)->nodeValue;
-          $price = $element->getElementsByTagName('SalesPrice')->item(0)->nodeValue;
-          $edit = $element->getElementsByTagName('EditSequence')->item(0)->nodeValue;
+  watchdog('session', dpr($_SESSION, TRUE, 'SalesReceiptModRs'), NULL, WATCHDOG_DEBUG);
+}
+
+// Response to a product search query
+// case 'ItemInventoryQueryRs':
+function uc_qb_response_item_inventory_query($response, $data, $status, $message) {
+  $product = $data;
+  if ($response['_retCount'] > 0) {
+    $model = $response[0]['Name'];
+    $id = $response[0]['ListID'];
+    $price = $response[0]['SalesPrice'];
+    $edit = $response[0]['EditSequence'];

-          // Make sure all orders ordering this product get the product data
+    // Make sure all orders ordering this product get the product data
-          foreach((array)$_SESSION['QBProducts'][$model]->order_id as $order_id) {
-            $_SESSION['qb_orders'][$order_id]->order_data['QBProducts'][$model] = array(
-              'id' => $id,
-              'model' => $model,
-              'price' => $price,
-              'edit' => $edit
-            );
+    $products = variable_get('uc_qb_products', array());
+    foreach((array)$products[$model]->order_id as $order_id) {
+      $products[$model]->id = $id;
+      $products[$model]->model = $model;
+      $products[$model]->price = $price;
+      $products[$model]->edit = $edit;
-          }
+    }
+    variable_set('uc_qb_products', $products);
-        }
-        // Create the product if it was not there
-        else {
+  }
+  // Create the product if it was not there
+  else {
-        	$new[] = array(
+    $request = array(
-            'name' => 'ItemInventoryAddRq',
-            'request' => array(
-              'ItemInventoryAdd' => array(
-                'Name' => $product->model,
-                'IsActive' => 'true',
-                'SalesDesc' => $product->title,
-                'SalesPrice' => $product->sell_price,
-                'IncomeAccountRef' => array(
+      'name' => 'ItemInventoryAddRq',
+      'request' => array(
+        'ItemInventoryAdd' => array(
+          'Name' => $product->model,
+          'IsActive' => 'true',
+          'SalesDesc' => $product->title,
+          'SalesPrice' => $product->sell_price,
+          'IncomeAccountRef' => array(
-                  'FullName' => variable_get('uc_qb_income_account', 'Merchandise Sales')
+            'FullName' => variable_get('uc_qb_income_account', 'Merchandise Sales'),
-                ),
+          ),
-                'PurchaseCost' => "0.0",
+          'PurchaseCost' => $product->cost,
-                'COGSAccountRef' => array(
+          'COGSAccountRef' => array(
-                  'FullName' => variable_get('uc_qb_cogs_account', 'Merchant Account Fees')
+            'FullName' => variable_get('uc_qb_cogs_account', 'Merchant Account Fees'),
-                ),
-                'AssetAccountRef' => array(
+          ),
+          'AssetAccountRef' => array(
-                  'FullName' => variable_get('uc_qb_asset_account', 'Inventory Asset')
+            'FullName' => variable_get('uc_qb_asset_account', 'Inventory Asset'),
-                ),
-                'ReorderPoint' => '',
-                'QuantityOnHand' => '',
-                'TotalValue' => '',
-                'InventoryDate' => date('Y-m-d', time()),
-              ),
+          ),
+          'ReorderPoint' => '',
+          'QuantityOnHand' => '',
+          'TotalValue' => '',
+          'InventoryDate' => date('Y-m-d', time()),
+        ),
-              'IncludeRetElement' => array('ListID', 'Name', 'SalesPrice', 'EditSequence')
+        'IncludeRetElement' => array('ListID', 'Name', 'SalesPrice', 'EditSequence'),
-            ),
+      ),
+      'data' => $product,
+      'callback' => array('uc_qb_response_item_inventory_add'),
-          );
+    );
+    qbwc_request_queue($request);
-        }
+  }
-      break;
-      // Save created inventory data
-      case 'ItemInventoryAddRs':
-        if ($statusCode == 0) {
-          $model = $element->getElementsByTagName('Name')->item(0)->nodeValue;
-          $id = $element->getElementsByTagName('ListID')->item(0)->nodeValue;
-          $price = $element->getElementsByTagName('SalesPrice')->item(0)->nodeValue;
-          $edit = $element->getElementsByTagName('EditSequence')->item(0)->nodeValue;
+  watchdog('session', dpr($_SESSION, TRUE, 'ItemInventoryQueryRs'), NULL, WATCHDOG_DEBUG);
+}
+
+// Save created inventory data
+// case 'ItemInventoryAddRs':
+function uc_qb_response_item_inventory_add($response, $data, $status, $message) {
+  if ($status == 0) {
+    $model = $response[0]['Name'];
+    $id = $response[0]['ListID'];
+    $price = $response[0]['SalesPrice'];
+    $edit = $response[0]['EditSequence'];

-          // Make sure all orders ordering this product get the product data
+    // Make sure all orders ordering this product get the product data
-          foreach((array)$_SESSION['QBProducts'][$model]->order_id as $order_id) {
-            $_SESSION['qb_orders'][$order_id]->order_data['QBProducts'][$model] = array(
-              'id' => $id,
-              'model' => $model,
-              'price' => $price,
-              'edit' => $edit
-            );
+    $products = variable_get('uc_qb_products', array());
+    foreach((array)$products[$model]->order_id as $order_id) {
+      $products[$model]->id = $id;
+      $products[$model]->model = $model;
+      $products[$model]->price = $price;
+      $products[$model]->edit = $edit;
-          }
+    }
+    variable_set('uc_qb_products', $products);
-        }
-        else {
-        	// Failed to add the product
+  }
+  else {
+    // Failed to add the product
-          watchdog('uc_qb', t('Failed to export the product %product in order #%order with error code %code (%message) to QB', array('%product' => $saved[$requestId]->title, '%order' => $saved[$requestId]->order_id, '%code' => $statusCode, '%message' => $statusMessage)), WATCHDOG_ERROR);
+    watchdog('uc_qb', 'Failed to export the product %product in order #%order with error code %code (%message) to QB', array('%product' => $data->title, '%order' => $data->order_id, '%code' => $status, '%message' => $message), WATCHDOG_ERROR);
-        }
+  }
-      break;
-      case 'ItemInventoryModRs':
-        if ($statusCode == 0) {
-          $model = $element->getElementsByTagName('Name')->item(0)->nodeValue;
-          $id = $element->getElementsByTagName('ListID')->item(0)->nodeValue;
-          $price = $element->getElementsByTagName('SalesPrice')->item(0)->nodeValue;
-          $edit = $element->getElementsByTagName('EditSequence')->item(0)->nodeValue;
+  watchdog('session', dpr($_SESSION, TRUE, 'ItemInventoryAddRs'), NULL, WATCHDOG_DEBUG);
+}
+
+// case 'ItemInventoryModRs':
+function uc_qb_response_item_inventory_mod($response, $data, $status, $message) {
+  if ($status == 0) {
+    $model = $response[0]['Name'];
+    $id = $response[0]['ListID'];
+    $price = $response[0]['SalesPrice'];
+    $edit = $response[0]['EditSequence'];

-          // Make sure all orders ordering this product get the product data
+    // Make sure all orders ordering this product get the product data
-          foreach((array)$_SESSION['QBProducts'][$model]->order_id as $order_id) {
-            $_SESSION['qb_orders'][$order_id]->order_data['QBProducts'][$model] = array(
-              'id' => $id,
-              'model' => $model,
-              'price' => $price,
-              'edit' => $edit
-            );
+    $products = variable_get('uc_qb_products', array());
+    foreach((array)$products[$model]->order_id as $order_id) {
+      $products[$model]->id = $id;
+      $products[$model]->model = $model;
+      $products[$model]->price = $price;
+      $products[$model]->edit = $edit;
-          }
+    }
+    variable_set('uc_qb_products', $products);
-        }
-        else {
-          // Failed to add the product
+  }
+  else {
+    // Failed to add the product
-          watchdog('uc_qb', t('Failed to change the product price of %product in order #%order with error code %code (%message) to QB', array('%product' => $saved[$requestId]->title, '%order' => $saved[$requestId]->order_id, '%code' => $statusCode, '%message' => $statusMessage)), WATCHDOG_ERROR);
+    watchdog('uc_qb', 'Failed to change the product price of %product in order #%order with error code %code (%message) to QB', array('%product' => $data->title, '%order' => $data->order_id, '%code' => $status, '%message' => $message), WATCHDOG_ERROR);
-        }
+  }
-      break;
-      case 'AccountQueryRs':
-        if (!isset($saved[$requestId])) {
-          $error = true;
-          break;
-        }
+  watchdog('session', dpr($_SESSION, TRUE, 'ItemInventoryModRs'), NULL, WATCHDOG_DEBUG);
+}

-        if ($returnCnt == 0) {
-          $new[] = array(
+// case 'AccountQueryRs':
+function uc_qb_response_account_query($response, $data, $status, $message) {
+  if ($response['_retCount'] == 0) {
+    $request = array(
-            'name' => 'AccountAddRq',
+      'name' => 'AccountAddRq',
-            'request' => array('AccountAdd' => array(
-              'Name' => $saved[$requestId]['name'],
-              'AccountType' => $saved[$requestId]['type'],
-            )),
-            'data' => $saved[$requestId]
+      'request' => array(
+        'AccountAdd' => array(
+          'Name' => $data['name'],
+          'AccountType' => $data['type'],
+        ),
+      ),
+      'data' => $data,
+      'callback' => array('uc_qb_response_account_add'),
-          );
+    );
+    qbwc_request_queue($request);
-        }
+  }
-      break;
-      case 'AccountAddRs':
-        if ($statusCode != 0) {
-          $error = true;
-          break;
+  else {
+    $accounts = variable_get('uc_qb_accounts', array());
+    $accounts[$data['name']] = TRUE;
+    variable_set('uc_qb_accounts', $accounts);
-        }
+  }
-      break;
-      case 'PreferencesQueryRs':
-        // Check that inventory and taxes are turned on
-        $taxes = $element->getElementsByTagName('SalesTaxPreferences');
-        $inventory = $element->getElementsByTagName('IsUsingInventory');
-        if ($taxes->length == 0) {
-        	// Taxes are not turned on. Will fail
-          watchdog('uc_qb', t('Failed to start QB export as taxes are not turned on in the company preferences.'), WATCHDOG_ERROR);
-          $error = true;
-          break;
-        }
-        if (!($inventory = $inventory->item(0)) || $inventory->nodeValue == 'false') {
-        	// Taxes are not turned on. Will fail
-          watchdog('uc_qb', t('Failed to start QB export as inventory is not turned on in the company preferences.'), WATCHDOG_ERROR);
-          $error = true;
-          break;
-        }
-      break;
-    }
-  }
+  watchdog('session', dpr($_SESSION, TRUE, 'AccountQueryRs'), NULL, WATCHDOG_DEBUG);
+}
-
+
-  // Stop processing on errors
-  if ($error) {
-    return -1;
+function uc_qb_response_account_add($response, $data, $status, $message) {
+  if ($status == 0) {
+    $accounts = variable_get('uc_qb_accounts', array());
+    $accounts[$data['name']] = TRUE;
+    variable_set('uc_qb_accounts', $accounts);
   }
+}

-  if (!empty($new)) {
-  	$_SESSION['qb_pending_requests'][] = $new;
+// case 'PreferencesQueryRs':
+function uc_qb_response_preferences_query($response, $data, $status, $message) {
+  // Check that inventory and taxes are turned on
+  $taxes = $response[0]['SalesTaxPreferences'];
+  $inventory = $response[0]['PurchasesAndVendorsPreferences']['IsUsingInventory'];
+  if (count($taxes) == 0) {
+    // Taxes are not turned on. Will fail
+    watchdog('uc_qb', 'Failed to start QB export as taxes are not turned on in the company preferences.', array(), WATCHDOG_ERROR);
+    return;
   }
-
-  if ($_SESSION['qb_orders_count'] == 0) {
-  	return 100;
+  if (!$inventory || $inventory == 'false') {
+    // Inventory not turned on. Will fail
+    watchdog('uc_qb', 'Failed to start QB export as inventory is not turned on in the company preferences.', array(), WATCHDOG_ERROR);
+    return;
   }
-
-	return ($done / $_SESSION['qb_orders_count']) * 100;
+  watchdog('session', dpr($_SESSION, TRUE, 'PreferencesQueryRs'), NULL, WATCHDOG_DEBUG);
 }

 /**
  * Implementation of hook_qbwc_request()
- *
+ *
  * @Description: Send requests for data from quickbooks (existing customers/orders)
  *    or requests for additions into Quickbooks
  */
 function uc_qb_qbwc_request() {
-  // Check if we have any pending requests to make as a response to QB returned data
-  if (!empty($_SESSION['qb_pending_requests'])) {
-  	return array_shift($_SESSION['qb_pending_requests']);
-  }
-
   // Get a list of orders needing exported
-  if (!isset($_SESSION['qb_started_processing'])) {
-    $_SESSION['qb_started_processing'] = true;
-    $checked_users = $products  = array();
+  $checks = $requests = array();
+  $orders = uc_qb_fetch_orders();
-
+
+  $accounts = variable_get('uc_qb_accounts', array());
+  if (empty($accounts)) {
     // Checks for accounts/settings to exist that need to happen on first connect
-    if (count($_SESSION['qb_orders'])) {
+    if ($orders) {
       // Check that certain required service accounts exist
       $services[] = array('name' => variable_get('uc_qb_income_account', 'Merchandise Sales'), 'type' => 'Income');
       $services[] = array('name' => variable_get('uc_qb_cogs_account', 'Merchant Account Fees'), 'type' => 'CostOfGoodsSold');
       $services[] = array('name' => variable_get('uc_qb_asset_account', 'Inventory Asset'), 'type' => 'OtherCurrentAsset');
+
       foreach($services as $service) {
-       $check[] = array(
+        $checks[] = array(
           'name' => 'AccountQueryRq',
           'request' => array(
             'FullName' => $service['name'],
             '_metaData' => 'MetaDataOnly'
           ),
-          'data' => $service
+          'data' => $service,
+          'callback' => array('uc_qb_response_account_query'),
         );
       }

-      $check[] = array(
+      $checks[] = array(
         'name' => 'PreferencesQueryRq',
-        'request' => array('IncludeRetElement' => array('SalesTaxPreferences', 'PurchasesAndVendorsPreferences')),
+        'request' => array(
+          'IncludeRetElement' => array(
+            'SalesTaxPreferences',
+            'PurchasesAndVendorsPreferences',
+          ),
+        ),
+        'callback' => array('uc_qb_response_preferences_query'),
       );
     }
+  }

-    $_SESSION['QBProducts'] = array();
-    $products = &$_SESSION['QBProducts'];
-    foreach($_SESSION['qb_orders'] as &$copy) {
+  $checked_users = array();
+  $products = variable_get('uc_qb_products', array());
+  foreach($orders as $order) {
-      // Check that all of the products exist in QB and if not create them
+    // Check that all of the products exist in QB and if not create them
-    	$product_result = db_query('SELECT uop.nid, uop.title, uop.model, uop.order_id, up.sell_price FROM {uc_order_products} uop INNER JOIN {uc_products} up ON uop.nid = up.nid WHERE uop.order_id = "%d"', $copy->order_id);
+    $product_result = db_query('SELECT uop.nid, uop.title, uop.model, uop.order_id, up.cost, up.sell_price FROM {uc_order_products} uop INNER JOIN {uc_products} up ON uop.nid = up.nid WHERE uop.order_id = %d', $order->order_id);
-      while ($product = db_fetch_object($product_result)) {
+    while ($product = db_fetch_object($product_result)) {
-        if (!array_key_exists($product->model, $products)) {
+      if (!isset($products[$product->model])) {
-          $product->order_id = array($product->order_id);
+        $product->order_id = array($product->order_id);
-          $check[] = array(
+        $checks[] = array(
-            'name' => 'ItemInventoryQueryRq',
-            'request' => array(
-              'FullName' => $product->model,
-              'IncludeRetElement' => array('ListID', 'Name', 'SalesPrice', 'EditSequence'),
-              '_metaData' => 'MetaDataAndResponseData'
-            ),
+          'name' => 'ItemInventoryQueryRq',
+          'request' => array(
+            'FullName' => $product->model,
+            'IncludeRetElement' => array('ListID', 'Name', 'SalesPrice', 'EditSequence'),
+            '_metaData' => 'MetaDataAndResponseData'
+          ),
-            'data' => $product
+          'data' => $product,
+          'callback' => array('uc_qb_response_item_inventory_query'),
-          );
-          $products[$product->model] = $product;
-        }
-        else {
-        	$products[$product->model]->order_id[] = $product->order_id;
-        }
-      }
+        );
+        $products[$product->model] = $product;
+      }
+      else {
+        $products[$product->model]->order_id[] = $product->order_id;
+      }
+    }
+    variable_set('uc_qb_products', $products);

-      // Check that all the customers exist in QB and if not create them
+    // Check that all the customers exist in QB and if not create them
-      if (!array_key_exists($copy->uid ? $copy->uid : $copy->primary_email, $checked_users)) {
-        if (isset($copy->user_data['QBListID'])) {
-          $copy->qb_user_id = $copy->user_data['QBListID'];
+    if (isset($order->user_data['QBListID'])) {
+      $order->qb_user_id = $order->user_data['QBListID'];
-        }
+    }
-        else if (isset($copy->order_data['QBListID'])) {
-          $copy->qb_user_id = $copy->order_data['QBListID'];
+    else if (isset($order->order_data['QBListID'])) {
+      $order->qb_user_id = $order->order_data['QBListID'];
-        }
+    }
-        else if (!$copy->primary_email) {
-        	watchdog('uc_qb', t('Order #%order could not be exported to QB because anonymous user did not provide an email address.', array('%order' => $copy->order_id)), WATCHDOG_ERROR);
+    else if (!$order->primary_email) {
+      watchdog('uc_qb', 'Order #%order could not be exported to QB because anonymous user did not provide an email address.', array('%order' => $order->order_id), WATCHDOG_ERROR);
-        }
-        else {
+    }
+    else {
-          $check[] = array(
+      if (!array_key_exists($order->uid ? $order->uid : $order->primary_email, $checked_users)) {
+        $checks[] = array(
-            'name' => 'CustomerAddRq',
+          'name' => 'CustomerAddRq',
-            'request' => array('CustomerAdd' => array(
-              'Name' => $copy->uid ? $copy->name : $copy->primary_email,
+          'request' => array(
+            'CustomerAdd' => array(
+              'Name' => $order->uid ? $order->name : $order->primary_email,
               'IsActive' => 'true',
-              'Email' => $copy->primary_email,
-              'Notes' => $copy->uid ? url('user/'. $copy->uid, null, null, true) : ' '
-            )),
-            'data' => $copy
+              'Email' => $order->primary_email,
+              'Notes' => $order->uid ? url('user/'. $order->uid, array('absolute' => TRUE)) : ' ',
+            ),
+          ),
+          'data' => $order,
+          'callback' => array('uc_qb_response_customer_add'),
-          );
+        );
-          $copy->qb_user_id_pending = true;
+        $order->qb_user_id_pending = TRUE;
-        }
+      }
-
-        $checked_users[$copy->uid ? $copy->uid : $copy->primary_email] = true;
-      }
+    }
-    }
-  }
-  else if (empty($_SESSION['qb_orders'])) {
-  	return;
+
+    $checked_users[$order->uid ? $order->uid : $order->primary_email] = TRUE;
+    //watchdog('uc_qb', dpr($order, TRUE, 'order'), NULL, WATCHDOG_DEBUG);
+    $orders[$order->order_id] = $order;
   }

-  $requests = array();
-  $first = true;
-  foreach($_SESSION['qb_orders'] as &$item) {
+  $first = TRUE;
+  foreach($orders as $item) {
     if ($item->order_data['QBProcessed']) {
       // This order was already processed
-    	continue;
+      continue;
     }

     $receipt = array();
@@ -605,67 +646,79 @@
     $order = uc_order_load($item->order_id);

     // Is there a better way to get at the customer message?
-    $message = db_result(db_query('SELECT message FROM {uc_order_comments} WHERE order_id = "%d" AND order_status = "pending" AND message != "-" LIMIT 1', $order->order_id));
+    $message = db_result(db_query_range('SELECT message FROM {uc_order_comments} WHERE order_id = %d AND order_status = "pending" AND message <> "-"', $order->order_id, 0, 1));
     $billing_country = uc_get_country_data(array('country_id' => $order->billing_country));
     $shipping_country = uc_get_country_data(array('country_id' => $order->delivery_country));

     // Check if shipping/payment methods are available. If not send a request for those instead
-    if ($order->quote['method'] && !array_key_exists($order->quote['method'], (array)$_SESSION['qb_shipping_methods'])) {
-      $check[] = array(
+    $shipping_methods = variable_get('uc_qb_shipping_methods', array());
+    if ($order->quote['method'] && !array_key_exists($order->quote['method'], (array)$shipping_methods)) {
+      $checks[] = array(
         'name' => 'ShipMethodQueryRq',
         'request' => array(
           'FullName' => $order->quote['method'],
-          '_metaData' => 'MetaDataOnly'
+          '_metaData' => 'MetaDataOnly',
         ),
-        'data' => $order->quote
+        'data' => $order->quote,
+        'callback' => array('uc_qb_response_ship_method_query'),
       );
     }

     // If payment methods are enabled, ensure that we have mapped values from UC -> QB
-    if (isset($order->payment_method) && !array_key_exists($order->payment_method, (array)$_SESSION['qb_payment_methods'])) {
-      $check[] = array(
+    $payment_methods = variable_get('uc_qb_payment_methods', array());
+    if (isset($order->payment_method) && !array_key_exists($order->payment_method, (array)$payment_methods)) {
+      $checks[] = array(
         'name' => 'PaymentMethodQueryRq',
         'request' => array(
           'FullName' => $order->payment_method,
-          '_metaData' => 'MetaDataOnly'
+          '_metaData' => 'MetaDataOnly',
         ),
-        'data' => $order->payment_method
+        'data' => $order->payment_method,
+        'callback' => array('uc_qb_response_payment_method_query'),
       );
     }
-
+
     // Make various checks on line items
+    $services = variable_get('uc_qb_services', array());
     foreach((array)$order->line_items as $line) {
       $line = (object)$line;
       if (_line_item_data($line->type, 'calculated') != TRUE) {
         continue;
       }

-      if (!array_key_exists($line->type, (array)$_SESSION['qb_services'])) {
-      	$check[] = array(
+      if (!array_key_exists($line->type, (array)$services)) {
+        $checks[] = array(
           'name' => 'ItemServiceQueryRq',
           'request' => array(
             'FullName' => $line->type,
-            '_metaData' => 'MetaDataOnly'
+            '_metaData' => 'MetaDataOnly',
           ),
-          'data' => $line->type
+          'data' => $line->type,
+          'callback' => array('uc_qb_response_item_service_query'),
         );
       }
     }

     if (!$item->qb_user_id_pending && !$item->qb_user_id) {
-    	// This should never happen. If it does, make a log entry for this order saying that it failed to get exported
+      // This should never happen. If it does, make a log entry for this order saying that it failed to get exported
-      $item->order_data['QBProcessed'] = true;
-      $_SESSION['qb_orders_count']--;
-      $_SESSION['qb_failed_orders'][] = $item;
-      watchdog('uc_qb', t('Order #%order_id failed to get exported to QB because the user did not exist in (failed to create properly) inside QB.', array('%order_id' => $item->order_id)), WATCHDOG_ERROR);
+      $item->order_data['QBProcessed'] = TRUE;
+
+      $failed_orders = qbwc_get('failed_orders');
+      $failed_orders[] = $item;
+      qbwc_set('failed_orders', $failed_orders);
+
+      watchdog('uc_qb', 'Order #%order_id failed to get exported to QB because the user did not exist in (failed to create properly) inside QB.', array('%order_id' => $item->order_id), WATCHDOG_ERROR);
       continue;
     }

     // If any check items were marked, send them all at once
-    if (!empty($check)) {
-    	return $check;
+    if (!empty($checks)) {
+      qbwc_set('orders', $orders);
+      watchdog('session', dpr($_SESSION, TRUE, 'hook_request return session'), NULL, WATCHDOG_DEBUG);
+      return $checks;
     }

+    //$requests = array();
     // Set the available info to get imported into QB
     $receipt['CustomerRef']['ListID'] = $item->qb_user_id;
     $receipt['TxnDate'] = date('Y-m-d', $order->created);
@@ -700,34 +753,34 @@
     );
     $receipt['IsPending'] = 'false';
     if ($order->payment_method) {
-    	$receipt['PaymentMethodRef']['FullName'] = $order->payment_method;
+      $receipt['PaymentMethodRef']['FullName'] = $order->payment_method;
     }
     if ($order->quote['method']) {
-    	$receipt['ShipMethodRef']['FullName'] = $order->quote['method'];
+      $receipt['ShipMethodRef']['FullName'] = $order->quote['method'];
     }
     $receipt['Memo'] = substr($message, 0, 101);
     $receipt['DepositToAccountRef']['FullName'] = variable_get('uc_qb1_income_account', 'Undeposited Funds');
     //$receipt['Other'] = 'CC:'. $order->payment_details['cc_number'] . ' UserID:'. $order->uid;

-    $added_products = false;
+    $added_products = FALSE;
     $total = 0;
     if (is_array($order->products) && count($order->products) > 0) {
       $lineItems = &$receipt['SalesReceiptLineAdd'];

       foreach ($order->products as $product) {
-        if (!$item->order_data['QBProducts'][$product->model]) {
+        if (!$products[$product->model]) {
           // The product was not created/set properly in QB
-          $added_products = false;
+          $added_products = FALSE;
           break;
         }

-        $description = $product->title .' x'. $product->qty;
+        $description = $product->title .' x '. $product->qty;
         if (is_array($product->data['attributes'])) {
           $description .= ', ';
-          $start = true;
+          $start = TRUE;
           foreach ($product->data['attributes'] as $key => $value) {
             if ($start) {
-              $start = false;
+              $start = FALSE;
             }
             else {
               $description .= ', ';
@@ -735,41 +788,44 @@
             $description .= $key .': '. $value;
           }
         }
-
+
-        if ($item->order_data['QBProducts'][$product->model]['price'] != $product->price) {
+        if ($products[$product->model]->price != $product->price) {
           // TODO: Change the price in QB of the product if it had been changed for this product
-        	$requests[] = array(
-
-          );
         }

         $product_line = array();
-        $product_line['ItemRef']['ListID'] = $item->order_data['QBProducts'][$product->model]['id'];
-        $product_line['Desc'] = substr($description, 0, 4000);
+        $product_line['ItemRef']['ListID'] = $products[$product->model]->id;
+        $product_line['Desc'] = htmlentities(substr($description, 0, 4000));
         $product_line['Quantity'] = $product->qty;
         $product_line['Rate'] = uc_currency_format($product->price, FALSE, FALSE, '.');
         $product_line['SalesTaxCodeRef']['FullName'] = 'NON';

-        $added_products = true;
+        $added_products = TRUE;
         $total += $product->qty * $product->price;
         $lineItems[] = $product_line;
       }
-
+
       if (!$added_products) {
         // Make sure to keep total orders to be processed up to date
-        $item->order_data['QBProcessed'] = true;
-        $_SESSION['qb_orders_count']--;
-        $_SESSION['qb_failed_orders'][] = $item;
-      	watchdog('uc_qb', t('Failed to export order #%order because some or all of the purchased products could not be created/found in QB.', array('%order' => $item->order_id)), WATCHDOG_ERROR);
+        $item->order_data['QBProcessed'] = TRUE;
+
+        $failed_orders = qbwc_get('failed_orders');
+        $failed_orders[] = $item;
+        qbwc_set('failed_orders', $failed_orders);
+
+        watchdog('uc_qb', 'Failed to export order #%order because some or all of the purchased products could not be created/found in QB.', array('%order' => $item->order_id), WATCHDOG_ERROR);
         continue;
       }
     }
     else {
       // Make sure to keep total orders to be processed up to date
-      $item->order_data['QBProcessed'] = true;
-      $_SESSION['qb_orders_count']--;
-      $_SESSION['qb_failed_orders'][] = $item;
-    	watchdog('uc_qb', t('Failed to export order #%order because no products were purchased.', array('%order' => $item->order_id)), WATCHDOG_ERROR);
+      $item->order_data['QBProcessed'] = TRUE;
+
+      $failed_orders = qbwc_get('failed_orders');
+      $failed_orders[] = $item;
+      qbwc_set('failed_orders', $failed_orders);
+
+      watchdog('uc_qb', 'Failed to export order #%order because no products were purchased.', array('%order' => $item->order_id), WATCHDOG_ERROR);
       continue;
     }

@@ -777,7 +833,7 @@
     foreach((array)$order->line_items as $line) {
       // Only look at calculated line items
       if (_line_item_data($line['type'], 'calculated') != TRUE) {
-      	continue;
+        continue;
       }
       $lineItems = &$receipt['SalesReceiptLineAdd'];

@@ -790,56 +846,65 @@
       $total += $line['amount'];
       $lineItems[] = $line_item;
     }
-
+
     // Add any customer messages as a blank line item
-    if ($message && variable_get('uc_qb_include_messages', true)) {
+    if ($message && variable_get('uc_qb_include_messages', TRUE)) {
       // Add two blank lines in front
       $receipt['SalesReceiptLineAdd'][] = array('Desc' => ' ');
       $receipt['SalesReceiptLineAdd'][] = array('Desc' => ' ');
-    	$receipt['SalesReceiptLineAdd'][] = array(
+      $receipt['SalesReceiptLineAdd'][] = array(
         'Desc' => substr($message, 0, 4000)
       );
     }

     // Only add items if we are calculating the total properly
     if (round($total, 2) == round($order->order_total, 2)) {
-    	$requests[] = array(
+      $requests[] = array(
         'name' => 'SalesReceiptAddRq',
         'request' => array(
           'SalesReceiptAdd' => $receipt,
           'IncludeRetElement' => array('RefNumber', 'TotalAmount', 'TxnID', 'EditSequence')),
-        'data' => $item
+        'data' => $item,
+        'callback' => array('uc_qb_response_sales_receipt_add'),
       );
     }
     else {
-    	$item->order_data['QBProcessed'] = true;
-      $_SESSION['qb_orders_count']--;
-      $_SESSION['qb_failed_orders'][] = $item;
-      watchdog('uc_qb', t('Failed to export order #%order the calculated total meant for QB did not match the order total.', array('%order' => $item->order_id)), WATCHDOG_ERROR);
+      $item->order_data['QBProcessed'] = TRUE;
+
+      $failed_orders = qbwc_get('failed_orders');
+      $failed_orders[] = $item;
+      qbwc_set('failed_orders', $failed_orders);
+
+      watchdog('uc_qb', 'Failed to export order #%order the calculated total meant for QB did not match the order total.', array('%order' => $item->order_id), WATCHDOG_ERROR);
       continue;
     }
-
+
-    $first = false;
+    $first = FALSE;
+    $orders[$item->order_id] = $item;
   }

+  qbwc_set('orders', $orders);
+  watchdog('session', dpr($_SESSION, TRUE, 'uc_qb_qbwc_request session'), NULL, WATCHDOG_DEBUG);
+  watchdog('session', dpr($requests, TRUE, 'requests'), NULL, WATCHDOG_DEBUG);
+
   return $requests;
 }

 /**
  * Implementation of hook qbwc_close()
- *
+ *
  * Send email alerts on failed orders
  */
 function uc_qb_qbwc_close($ticket) {
-	if (!empty($_SESSION['qb_failed_orders']) && ($mail = variable_get('uc_qb_failed_orders_email', ''))) {
+  if (!empty($_SESSION['qb_failed_orders']) && ($mail = variable_get('uc_qb_failed_orders_email', ''))) {
     foreach($_SESSION['qb_failed_orders'] as $order) {
-    	$orders[] = t('#%order (@link)', array('%order' => $order->order_id, '@link' => url('fleurville/admin/store/orders/'. $order->order_id, null, null, true)));
+      $orders[] = t('#%order (@link)', array('%order' => $order->order_id, '@link' => url('fleurville/admin/store/orders/'. $order->order_id, array('absolute' => TRUE))));
     }
-
+
     $output = t('There were errors exporting the following orders to QB via Web Connector: ') . "\n\n";
     $output .= implode("\n", $orders) . "\n\n";
-    $output .= t('To find more details about the errors, view the error logs at %url and filter by "uc_qb"', array('%url' => url('admin/logs/watchdog', null, null, true)));
+    $output .= t('To find more details about the errors, view the error logs at %url and filter by "uc_qb"', array('%url' => url('admin/reports/watchdog', array('absolute' => TRUE))));

-		drupal_mail('uc_qb_failed_exports', $mail, t('Errors exporting orders to QB'), $output, uc_store_email_from());
-	}
+    drupal_mail('uc_qb_failed_exports', $mail, t('Errors exporting orders to QB'), $output, uc_store_email_from());
+  }
 }
