diff -Nurp --exclude='\.svn' ./qb.module ../../modules/qb/qb.module
--- ./qb.module	2008-09-02 15:38:28.000000000 +0900
+++ ../../modules/qb/qb.module	2008-09-02 15:35:50.000000000 +0900
@@ -4,7 +4,7 @@ function qb_menu($may_cache = true) {
   $items = array();
 
   if ($may_cache) {
-    $items[] = array(
+  	$items[] = array(
       'path' => 'admin/settings/qb',
       'title' => t('Quickbooks Settings'),
       'callback' => 'drupal_get_form',
@@ -20,6 +20,9 @@ function qb_perm() {
   return array('administer quickbooks');
 }
 
+/**
+ * Menu callback to set module settings
+ */
 function qb_settings() {
   $form = array();
 
@@ -27,31 +30,68 @@ function qb_settings() {
     '#type'        => 'textfield',
     '#title'       => t('Company file'),
     '#description' => t('The full path to your quickbooks company file, e.g. C:\Data\MyCompany\MyCompany.qdb.  If you leave this blank, applications will use the file that is currently open on your workstation.'),
+    '#default_value' => variable_get('qb_company_file', '')
   );
-  // Make sure the buttons show up someplace responsible.
-  $form['buttons'] = array('#weight' => 10);
 
   return system_settings_form($form);
 }
 
-function qb_qbxml($root_entity, $elements) {
-  $qbxml = new DOMDocument('1.0');
-  $xml = $qbxml->appendChild($qbxml->createElement($root_entity));
-  foreach ($elements as $name => $value) {
-    _qb_qbxml_node($qbxml, $name, $value, $xml);
+function qb_qbxml($elements, $root = array('QBXML')) {
+  $qbxml = $xml = new DOMDocument('1.0');
+  
+  // Make sure the root is an array so _qb_qbxml_node can process it properly
+  if (!is_array($root)) {
+  	$root = array($root => array());
+  }
+
+  // Attach the base/common root of the document
+  $start = _qb_qbxml_node($qbxml, key($root), current($root), $xml);
+
+  // Attach the rest of the document
+  foreach((array)$elements as $key => $element) {
+  	_qb_qbxml_node($qbxml, $key, $element, $start);
   }
+
   return $qbxml->saveXML();
 }
 
 function _qb_qbxml_node(&$doc, $name, $value, &$parent) {
-  if (is_string($value)) {
+  // Store the elements in the order they were added to the doc
+  static $added;
+
+  if (is_scalar($value)) {
     $element = $doc->createElement($name, $value);
+    $parent->appendChild($element);
   }
   if (is_array($value)) {
-    $element = $doc->createElement($name);
-    foreach ($value as $k => $v) {
-      _qb_qbxml_node($doc, $k, $v, $element);
+    if (is_numeric(key($value))) {
+      for($k=0;$v=$value[$k];$k++) {
+    		_qb_qbxml_node($doc, $name, $v, $parent);
+    	}
+    }
+    else {
+    	$element = $doc->createElement($name);
+      foreach ($value as $k => $v) {
+        // Denote attributes as starting with a _
+        if (is_scalar($v) && strpos($k, '_') === 0) {
+        	$k = substr($k, 1);
+          $attr = $doc->createAttribute($k);
+          $attr->appendChild($doc->createTextNode($v));
+          $element->appendChild($attr);
+        }
+        // Denote processing instructions with a ?
+        else if (is_scalar($v) && strpos($k, '?') === 0) {
+          $k = substr($k, 1);
+        	$doc->appendChild($doc->createProcessingInstruction($k, $v));
+        }
+        else {
+        	_qb_qbxml_node($doc, $k, $v, $element);
+        }
+      }
+      $added[] = $parent->appendChild($element);
     }
   }
-  $parent->appendChild($element);
+
+  // Try and return the last added element (first in the array because of recursion) to help have a more complex "root" as specified in qb_qbxml
+  return reset($added);
 }
diff -Nurp --exclude='\.svn' ./qbwc.inc ../../modules/qb/qbwc.inc
--- ./qbwc.inc	2008-09-02 15:44:02.000000000 +0900
+++ ../../modules/qb/qbwc.inc	2008-09-02 15:35:50.000000000 +0900
@@ -1,30 +1,34 @@
 <?php
 
 class qbwc {
+  // We cannot get back the original Server SOAP object, but we can at least load the right session getting our session variables back
+  // A way to expire these sessions would be nice....
   function _session($ticket) {
-    global $user;
-
-    $session = db_fetch_object(db_query("SELECT * FROM {qbwc_sessions} WHERE ticket = '%s'", $ticket));
-
-    // Session is closed.
-    if ($session->close_ts) {
-      return false;
+    $uid = db_result(db_query('SELECT uid FROM {sessions} WHERE sid = "%s" AND hostname = "%s"', $ticket, $_SERVER['REMOTE_ADDR']));
+    if ($uid && $ticket != session_id()) {
+    	global $user;
+    	$user = user_load(array('uid' => $user));
+
+      session_destroy();
+      session_id($ticket);
+      // Pretend that cookies are enabled so we can get back our session
+      $_COOKIE[session_name()] = true;
+      session_set_save_handler('sess_open', 'sess_close', 'sess_read', 'sess_write', 'sess_destroy_sid', 'sess_gc');
+      session_start();
+    }
+    else if (!$uid) {
+    	// Invalid session
+      exit;
     }
-
-    // Switch to the Quickbooks user.
-    if ($user->uid == 0) $user = user_load(array('uid' => $session->uid));
-
-    return $session; ;
   }
 
   function authenticate($params) {
     $name = $params->strUserName;
     $pass = $params->strPassword;
-
     $hostname = $_SERVER['REMOTE_ADDR'];
 
-    // Generate a ticket to be used for all further communication
-    $ticket = md5(time() . $name);
+    // Use the current session id as the ticket
+    $ticket = session_id();
 
     // Default result: "non-valid user credentials".
     $ret = 'nvu';
@@ -36,30 +40,35 @@ class qbwc {
     // Authenticate as the quickbooks drupal user
     if ($name && ($name == variable_get('qbwc_user', ''))) {
       if ($user = user_authenticate($name, $pass)) {
+        // Set nothing to do until a module decides it has something to do
+        $ret = 'none';
 
-        // Return company file or empty, which means "currently open file".
-        $ret = variable_get('qb_company_file', '');
-
-        if ($theres_nothing_to_do) { // TODO 
-          $ret = 'none';
+        // Let modules return whether they have work to do or not
+        // If no modules return anything, assume no work
+        foreach(module_implements('qbwc_authenticate') as $module) {
+          if (module_invoke($module, 'qbwc_authenticate', $ticket, $user)) {
+            // Return company file or empty, which means "currently open file" when work has been set
+            $ret = variable_get('qb_company_file', '');
+          }
         }
       }
     }
 
-    // Close the session immediately if the authentication failed.
-    $close_ts = ($ret == 'nvu' ) ? time() : 'NULL';
-    db_query("INSERT INTO {qbwc_sessions} ( ticket, hostname, uid, open_ts, close_ts ) VALUES ( '%s', '%s', %d, %d, $close_ts )", $ticket, $hostname, $user->uid, time());
-
     $result = array($ticket, $ret, $next_update, $minimum_wait);
     return (object) array('authenticateResult' => $result);
   }
 
   function closeConnection($params) {
     $ticket = $params->ticket;
+    $this->_session($ticket);
     global $user;
+    
+    // Let modules know we are closing the session
+    module_invoke_all('qbwc_close', $ticket);
 
     // Close the session and log it just like user_logout() sans drupal_goto.
-    watchdog('user', 'Session closed for %name.', array('%name' => $user->name));
+    watchdog('user', t('Session closed for %name.', array('%name' => $user->name)));
+
     // Destroy the current session.
     session_destroy();
     module_invoke_all('user', 'logout', NULL, $user);
@@ -67,12 +76,12 @@ class qbwc {
     // Load the anonymous user.
     $user = drupal_anonymous_user(); 
 
-    db_query("UPDATE {qbwc_sessions} SET close_ts = %d where ticket = '%s'", time(), $ticket);
-
     return (object) array( 'closeConnectionResult' => t('Session closed'));
   }
 
   function connectionError($ticket, $hresult, $message) {
+    // Do not try to reconnect
+    return 'done';
   }
 
   function getLastError($ticket) {
@@ -84,62 +93,140 @@ class qbwc {
   }
 
   function sendRequestXML($params) {
+    static $requestId = 1;
+
     $ticket = $params->ticket;
     $HCPResponse = $params->strHCPResponse;
     $company_file = $params->strCompanyFileName;
     $country = $params->qbXMLCountry;
     $major_version = $params->qbXMLMajorVers;
     $minor_version = $params->qbXMLMinorVers;
-    
-    $session = $this->_session($ticket);
+
+    $this->_session($ticket);
 
     // Default: If the web service has no requests to send, use an empty string.
     $ret = '';
 
     // Decide if we have anything to do and return qbxml.
-    if($requests = module_invoke_all('qbwc_request', $session)) {
-      foreach ( $requests as $r ) {
-        $ret .= qb_qbxml($r['name'], $r['request']);
+    $requests = array();
+    $_SESSION['requestIds'] = $_SESSION['savedData'] = array();
+
+    foreach(module_implements('qbwc_request') as $module) {
+      $request = module_invoke($module, 'qbwc_request');
+
+      // Make sure we have an array of requests instead of just a request
+      if (is_array($request) && !is_numeric(key($request))) {
+      	$request = array($request);
+      }
+
+      foreach((array)$request as $r) {
+        // Set data that module response/request handlers would like to pass between them
+        // during calls to QB
+        if (isset($r['data'])) {
+        	$_SESSION['savedData'][$requestId] = $r['data'];
+        }
+
+        // Attach request ids so we know how to send responses back to the right modules
+        // If modules set it to their own, we'll have to leave it up to them to avoid conflicts for now'
+        if (!isset($r['_requestId'])) {
+          $r['request']['_requestID'] = $requestId;
+          $_SESSION['requestIds'][$requestId++] = $module;
+        }
+
+        if ($r['name']) {
+        	$requests[$r['name']][] = $r['request'];
+        }
       }
     }
 
+    // Formulate the common base XML for all QBWC requests, using QBXML v5.0
+    $top = array(
+      'QBXML' => array(
+        '?qbxml' => 'version="5.0"', // XML processing instruction
+        'QBXMLMsgsRq' => array(
+          '_onError' => 'stopOnError' // XML attribute
+        )
+      )
+    );
+
+    $ret = qb_qbxml($requests, $top);
+
     return (object) array( 'sendRequestXMLResult' => $ret );
   }
 
   function receiveResponseXML($params) {
     $ticket = $params->ticket;
-    $response = $params->response;
+    $response = DOMDocument::loadXML($params->response);
     $hresult = $params->hresult;
     $message = $params->message;
+    $this->_session($ticket);
+    // Get the list of data stored for this response
+    $data = $_SESSION['savedData'];
+
+    // Split out the response elements so they can be sent to the appropriate modules
+    $elements = array();
+    if (is_object($response)) {
+      $top = $response->getElementsByTagName('QBXMLMsgsRs')->item(0);
+      for($i=0;$element = $top->childNodes->item($i); $i++) {
+        if ($element->nodeType == 3) {
+          // Skip #text node types
+        	continue;
+        }
+        $requestId = $element->getAttribute('requestID');
+        if ($module = $_SESSION['requestIds'][$requestId]) {
+          $elements[$module][] = $element;
+          
+          // Set the saved data for this modules requests
+          if ($data[$requestId]) {
+          	$saved[$module][$requestId] = $data[$requestId];
+          }
+        }
+      }
+    }
 
-    $session = $this->_session($ticket);
-
-    /* A positive integer from 1-100 represents the percentage of work 
-      completed, where value of 100 means there is no more work. A negative 
-      value means an error has occurred and Web Connector calls getLastError.
-    */
-    if($responses = module_invoke_all('qbwc_response', $session, $response, $hresult, $message)) {
-      $ret = 0;
-      foreach ($responses as $item) {
-        $ret += $item;
+    $done = 0;
+    $total = 0;
+    foreach(module_implements('qbwc_response') as $module) {
+    	$ret = module_invoke($module, 'qbwc_response', $elements[$module], $hresult, $message, $saved[$module]);
+      // Only count returned values less than 100
+      if (is_numeric($ret) && $ret <= 100) {
+        /* A positive integer from 1-100 represents the percentage of work 
+            completed, where value of 100 means there is no more work. A negative 
+            value means an error has occurred and Web Connector calls getLastError.
+          */
+      	$done += $ret;
+        $total++;
       }
-      $ret = $ret / count($responses);
     }
 
-    if (!isset($ret)) $ret = 100;
+    // Put the accumulation of returned percentages with the total into one total percentage
+    if ($total) {
+    	$done = $done / $total;
+    }
+    else {
+    	$done = 100;
+    }
+
+    // If it runs this long, something is probably wrong...
+    if ($_SESSION['countTimes']++ == 30) {
+    	$done = 100;
+    }
 
-    return (object) array( 'receiveResponseXMLResult' => $ret );
+    return (object) array( 'receiveResponseXMLResult' => $done );
   }
 
-  /* Unimplemented functions
+  // Unimplemented functions
 
   function getInteractiveURL($ticket, $session_id) {
+    $this->_session($ticket);
   }
 
   function interactiveDone($ticket) {
+    $this->_session($ticket);
   }
 
   function interactiveRejected($ticket, $reason) {
+    $this->_session($ticket);
   }
 
 
@@ -147,6 +234,4 @@ class qbwc {
   // the client's version.  It could be used to set a minimum version level.
   function clientVersion($version) {
   }
-
-  */
 }
diff -Nurp --exclude='\.svn' ./qbwc.install ../../modules/qb/qbwc.install
--- ./qbwc.install	2008-09-02 15:50:30.000000000 +0900
+++ ../../modules/qb/qbwc.install	2008-08-20 06:19:47.000000000 +0900
@@ -1,39 +1,16 @@
-<?php // $Id: qbwc.install,v 1.2 2008/06/16 16:12:50 vauxia Exp $
+<?php 
+// $Id: $
 
 function qbwc_install() {
-  variable_set('qbwc_owner_id', uniqid());
-  variable_set('qbwc_file_id', uniqid());
-  
-  switch ($GLOBALS['db_type']) {
-    case 'mysql':
-    case 'mysqli':
-      db_query("
-      CREATE TABLE {qbwc_sessions} (
-        ticket varchar(64) NOT NULL default '',
-        uid int unsigned NOT NULL default '0',
-        hostname varchar(15) NOT NULL default '',
-        open_ts int NOT NULL default '0',
-        close_ts int default '0',
-        PRIMARY KEY  (ticket)
-      ) /*!40100 DEFAULT CHARACTER SET utf8 */;
-      ");
-      break;
-    case 'pgsql':
-      db_query("CREATE TABLE {qbwc_sessions} (
-        ticket varchar(64) NOT NULL default '',
-        uid int NOT NULL default '0',
-        hostname varchar(15) NOT NULL default '',
-        open_ts int NOT NULL default '0',
-        close_ts int default '0',
-        PRIMARY KEY (ticket)
-      )");
-      break;
+  // Generate unique IDs for this QWC file
+  $part = array();
+  foreach(array(8,4,4,4,12) as $len) {
+    $part[] = substr(str_pad(base_convert(rand(), 10, 16), $len, "0", STR_PAD_LEFT), 0, $len);
   }
+
+  variable_set('qbwc_owner_id', implode('-', $part));
 }
 
 function qbwc_uninstall() {
   variable_del('qbwc_owner_id');
-  variable_del('qbwc_file_id');
-  
-  db_query('DROP TABLE {qbwc_sessions}');
 }
diff -Nurp --exclude='\.svn' ./qbwc.module ../../modules/qb/qbwc.module
--- ./qbwc.module	2008-09-02 15:53:48.000000000 +0900
+++ ../../modules/qb/qbwc.module	2008-09-02 15:35:50.000000000 +0900
@@ -9,7 +9,7 @@ function qbwc_menu($may_cache = true) {
       'path' => 'qbwc',
       'callback' => 'qbwc',
       'type' => MENU_CALLBACK,
-      'access' => user_access('access qbwc')
+      'access' => true
     );
     $items[] = array(
       'title' => t('QWC File'),
@@ -18,6 +18,14 @@ function qbwc_menu($may_cache = true) {
       'access' => user_access('access qbwc'),
       'type' => MENU_CALLBACK,
     );
+    $items[] = array(
+      'title' => t('Quickbooks Web Connector Setup'),
+      'path' => 'admin/settings/qb/qbwc',
+      'callback' => 'drupal_get_form',
+      'callback arguments' => array('qbwc_settings'),
+      'access' => user_access('access qbwc'),
+      'type' => MENU_LOCAL_TASK
+    );
   }
 
   return $items;
@@ -27,67 +35,70 @@ function qbwc_perm() {
   return array('access qbwc');
 }
 
-function qbwc_form_alter($form_id, &$form) {
-  // Add QBWC settings to the Quickbooks settings page
-  if ($form_id == 'qb_settings') {
-    $form['qbwc'] = array( 
-      '#title' => t('Web Connector settings'),
-      '#type' => 'fieldset', 
-      '#collapsible' => TRUE 
-    );
-
-    $form['qbwc']['qbwc_url'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Web Connector URL'),
-      '#description' => t('The URL the Web Connector will use to communicate with your Drupal site.  Please note that it MUST be SSL if the hostname is not "localhost"'),
-      '#default_value' => variable_get('qbwc_url', str_replace('http:', 'https:', url('qbwc', array('absolute' => TRUE)))),
-    );
-
-    $form['qbwc']['qbwc_user'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Quickbooks user'),
-      '#description' => t('This is the user that will be used to effect Quickbooks transactions.  You can use an existing user, but you probably want to create a user for this purpose'),
-      '#autocomplete_path' => 'user/autocomplete',
-      '#default_value' => variable_get('qbwc_user', ''),
-    );
-
-    $form['qbwc']['qbwc_hostname'] = array(
-      '#type'        => 'textfield',
-      '#title'       => t('IP Restriction'),
-      '#description' => t('If you want to limit connections to the Web Connector service to a limited set of hosts, enter one or more IP addresses here, separated by commas.'),
-    );
-
-    $options = array(
-      0  => t('Manually (No scheduling)'),
-      5  => t('Every 5 minutes'),
-      15 => t('Every 15 minutes'),
-      60 => t('Every hour'),
-      240 => t('Every 4 hours'),
-      480 => t('Every 8 hours'),
-      480 => t('Every 8 hours'),
-      720 => t('Every 12 hours'),
-      1440 => t('Once per day'),
-    );
-    $form['qbwc']['qbwc_scheduler'] = array(
-      '#type'        => 'select',
-      '#title'       => 'Run the Web Connector...',
-      '#description' => t('Select the time interval you wish to poll this site for updates.'),
-      '#default_value' => variable_get('qbwc_scheduler', 0),
-      '#options' => $options,
-    );
-
-    $form['qbwc']['qbwc_qwc'] = array(
-      '#type' => 'markup',
-      '#value' => l(t('Download QWC file'), 'admin/settings/qb/qwc'),
-    );
-  }
+function qbwc_settings() {
+  $form['qbwc'] = array( 
+    '#title' => t('Web Connector settings'),
+    '#type' => 'fieldset', 
+    '#collapsible' => TRUE 
+  );
+
+  $form['qbwc']['qbwc_url'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Web Connector URL'),
+    '#description' => t('The URL the Web Connector will use to communicate with your Drupal site.  Please note that it MUST be SSL if the hostname is not "localhost"'),
+    '#default_value' => variable_get('qbwc_url', str_replace('http:', 'https:', url('qbwc', null, null, true))),
+  );
+
+  $form['qbwc']['qbwc_user'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Quickbooks user'),
+    '#description' => t('This is the user that will be used to effect Quickbooks transactions.  You can use an existing user, but you probably want to create a user for this purpose'),
+    '#autocomplete_path' => 'user/autocomplete',
+    '#default_value' => variable_get('qbwc_user', ''),
+  );
+
+  $form['qbwc']['qbwc_hostname'] = array(
+    '#type'        => 'textfield',
+    '#title'       => t('IP Restriction'),
+    '#description' => t('If you want to limit connections to the Web Connector service to a limited set of hosts, enter one or more IP addresses here, separated by commas.'),
+  );
+
+  $options = array(
+    0  => t('Manually (No scheduling)'),
+    5  => t('Every 5 minutes'),
+    15 => t('Every 15 minutes'),
+    60 => t('Every hour'),
+    240 => t('Every 4 hours'),
+    480 => t('Every 8 hours'),
+    480 => t('Every 8 hours'),
+    720 => t('Every 12 hours'),
+    1440 => t('Once per day'),
+  );
+  $form['qbwc']['qbwc_scheduler'] = array(
+    '#type'        => 'select',
+    '#title'       => 'Run the Web Connector...',
+    '#description' => t('Select the time interval you wish to poll this site for updates.'),
+    '#default_value' => variable_get('qbwc_scheduler', 0),
+    '#options' => $options,
+  );
+
+  $form['qbwc']['qbwc_qwc'] = array(
+    '#type' => 'markup',
+    '#value' => l(t('Download QWC file'), 'admin/settings/qb/qwc'),
+  );
+  
+  return system_settings_form($form);
 }
 
 function qbwc_qwc() {
-// TODO generate these!
-variable_set('qbwc_file_id', '72832751-65dc-11db-bd13-0800200c9a66');
-variable_set('qbwc_owner_id', '72832751-65dc-11db-bd13-0800200c9a66');
   $elements = array();
+  
+  // Generate a FileID for this application file
+  $part = array();
+  foreach(array(8,4,4,4,12) as $len) {
+    $part[] = substr(str_pad(base_convert(rand(), 10, 16), $len, "0", STR_PAD_LEFT), 0, $len);
+  }
+
   $elements['AppName'] = variable_get('site_name', 'Drupal');
   $elements['AppID'] = '';
   $elements['AppURL'] = variable_get('qbwc_url', '');
@@ -95,27 +106,28 @@ variable_set('qbwc_owner_id', '72832751-
   $elements['AppSupport'] = variable_get('qbwc_url', '') .'/support';
   $elements['UserName'] = variable_get('qbwc_user', '');
   $elements['OwnerID'] = '{' . variable_get('qbwc_owner_id', '') . '}';
-  $elements['FileID'] = '{' . variable_get('qbwc_file_id', '') . '}';
+  $elements['FileID'] = '{' . implode('-', $part) . '}';
   $elements['QBType'] = 'QBFS'; // Used with QB Financial systems, not POS.
   if ($minutes = variable_get('qbwc_scheduler', 0)) {
     $elements['Scheduler'] = array();
     $elements['Scheduler']['RunEveryNMinutes'] = $minutes;
   }
 
-  $xml = qb_qbxml('QBWCXML', $elements);
+  $xml = qb_qbxml($elements, 'QBWCXML');
 
-  header('Content-type: application/force-download');
-  header('Content-Transfer-Encoding: Binary');
-  header('Content-length: ' . strlen($xml));
-  header('Content-disposition: attachment; filename=drupal.qwc');
+  drupal_set_header('Content-type: application/force-download');
+  drupal_set_header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
+  drupal_set_header('Content-Transfer-Encoding: Binary');
+  drupal_set_header('Content-length: ' . strlen($xml));
+  drupal_set_header('Content-disposition: attachment; filename=drupal.qwc');
   echo $xml;
+  exit;
 }
 
 function qbwc() {
-  global $base_path;
+  global $base_path, $base_url;
   require_once dirname(__FILE__) . '/qbwc.inc';
-  $wsdl = 'http://developer.intuit.com/uploadedFiles/Support/QBWebConnectorSvc.wsdl';
-  $wsdl = 'https://dev/sites/qb/modules/qb/QBWebConnectorSvc.wsdl?'.time();
+  $wsdl = $base_url .'/'. drupal_get_path('module', 'qbwc') .'/qbwc.wsdl';
   $qbwc = new SoapServer($wsdl, array('uri' => variable_get('qbwc_url', '')));
   $qbwc->setClass('qbwc');
   $qbwc->setPersistence(SOAP_PERSISTENCE_SESSION);
diff -Nurp --exclude='\.svn' ./qbwc.wsdl ../../modules/qb/qbwc.wsdl
--- ./qbwc.wsdl	1970-01-01 09:00:00.000000000 +0900
+++ ../../modules/qb/qbwc.wsdl	2008-07-23 12:11:49.000000000 +0900
@@ -0,0 +1,312 @@
+<?xml version="1.0" encoding="utf-8"?>
+<wsdl:definitions xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://developer.intuit.com/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" targetNamespace="http://developer.intuit.com/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
+  <wsdl:types>
+    <s:schema elementFormDefault="qualified" targetNamespace="http://developer.intuit.com/">
+      <s:element name="authenticate">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="strUserName" type="s:string" />
+            <s:element minOccurs="0" maxOccurs="1" name="strPassword" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="authenticateResponse">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="authenticateResult" type="tns:ArrayOfString" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:complexType name="ArrayOfString">
+        <s:sequence>
+          <s:element minOccurs="0" maxOccurs="unbounded" name="string" nillable="true" type="s:string" />
+        </s:sequence>
+      </s:complexType>
+
+<!-- added these two methods -->
+	<s:element name="serverVersion">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="strVersion" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="serverVersionResponse">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="serverVersionResult" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="clientVersion">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="strVersion" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="clientVersionResponse">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="clientVersionResult" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+
+
+      <s:element name="sendRequestXML">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="ticket" type="s:string" />
+            <s:element minOccurs="0" maxOccurs="1" name="strHCPResponse" type="s:string" />
+            <s:element minOccurs="0" maxOccurs="1" name="strCompanyFileName" type="s:string" />
+            <s:element minOccurs="0" maxOccurs="1" name="qbXMLCountry" type="s:string" />
+            <s:element minOccurs="1" maxOccurs="1" name="qbXMLMajorVers" type="s:int" />
+            <s:element minOccurs="1" maxOccurs="1" name="qbXMLMinorVers" type="s:int" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="sendRequestXMLResponse">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="sendRequestXMLResult" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="receiveResponseXML">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="ticket" type="s:string" />
+            <s:element minOccurs="0" maxOccurs="1" name="response" type="s:string" />
+            <s:element minOccurs="0" maxOccurs="1" name="hresult" type="s:string" />
+            <s:element minOccurs="0" maxOccurs="1" name="message" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="receiveResponseXMLResponse">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="1" maxOccurs="1" name="receiveResponseXMLResult" type="s:int" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="connectionError">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="ticket" type="s:string" />
+            <s:element minOccurs="0" maxOccurs="1" name="hresult" type="s:string" />
+            <s:element minOccurs="0" maxOccurs="1" name="message" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="connectionErrorResponse">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="connectionErrorResult" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="getLastError">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="ticket" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="getLastErrorResponse">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="getLastErrorResult" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="closeConnection">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="ticket" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+      <s:element name="closeConnectionResponse">
+        <s:complexType>
+          <s:sequence>
+            <s:element minOccurs="0" maxOccurs="1" name="closeConnectionResult" type="s:string" />
+          </s:sequence>
+        </s:complexType>
+      </s:element>
+    </s:schema>
+  </wsdl:types>
+
+  <wsdl:message name="authenticateSoapIn">
+    <wsdl:part name="parameters" element="tns:authenticate" />
+  </wsdl:message>
+  <wsdl:message name="authenticateSoapOut">
+    <wsdl:part name="parameters" element="tns:authenticateResponse" />
+  </wsdl:message>
+
+<!-- added this part -->
+  <wsdl:message name="serverVersionSoapIn">
+    <wsdl:part name="parameters" element="tns:serverVersion" />
+  </wsdl:message>
+  <wsdl:message name="serverVersionSoapOut">
+    <wsdl:part name="parameters" element="tns:serverVersionResponse" />
+  </wsdl:message>
+  <wsdl:message name="clientVersionSoapIn">
+    <wsdl:part name="parameters" element="tns:clientVersion" />
+  </wsdl:message>
+  <wsdl:message name="clientVersionSoapOut">
+    <wsdl:part name="parameters" element="tns:clientVersionResponse" />
+  </wsdl:message>
+
+
+  <wsdl:message name="sendRequestXMLSoapIn">
+    <wsdl:part name="parameters" element="tns:sendRequestXML" />
+  </wsdl:message>
+  <wsdl:message name="sendRequestXMLSoapOut">
+    <wsdl:part name="parameters" element="tns:sendRequestXMLResponse" />
+  </wsdl:message>
+  <wsdl:message name="receiveResponseXMLSoapIn">
+    <wsdl:part name="parameters" element="tns:receiveResponseXML" />
+  </wsdl:message>
+  <wsdl:message name="receiveResponseXMLSoapOut">
+    <wsdl:part name="parameters" element="tns:receiveResponseXMLResponse" />
+  </wsdl:message>
+  <wsdl:message name="connectionErrorSoapIn">
+    <wsdl:part name="parameters" element="tns:connectionError" />
+  </wsdl:message>
+  <wsdl:message name="connectionErrorSoapOut">
+    <wsdl:part name="parameters" element="tns:connectionErrorResponse" />
+  </wsdl:message>
+  <wsdl:message name="getLastErrorSoapIn">
+    <wsdl:part name="parameters" element="tns:getLastError" />
+  </wsdl:message>
+  <wsdl:message name="getLastErrorSoapOut">
+    <wsdl:part name="parameters" element="tns:getLastErrorResponse" />
+  </wsdl:message>
+  <wsdl:message name="closeConnectionSoapIn">
+    <wsdl:part name="parameters" element="tns:closeConnection" />
+  </wsdl:message>
+  <wsdl:message name="closeConnectionSoapOut">
+    <wsdl:part name="parameters" element="tns:closeConnectionResponse" />
+  </wsdl:message>
+  <wsdl:portType name="QBWebConnectorSvcSoap">
+	
+	<!-- add this chunk -->
+	<wsdl:operation name="serverVersion">
+      <wsdl:input message="tns:serverVersionSoapIn" />
+      <wsdl:output message="tns:serverVersionSoapOut" />
+    </wsdl:operation>
+	<wsdl:operation name="clientVersion">
+      <wsdl:input message="tns:clientVersionSoapIn" />
+      <wsdl:output message="tns:clientVersionSoapOut" />
+    </wsdl:operation>
+
+
+    <wsdl:operation name="authenticate">
+      <wsdl:input message="tns:authenticateSoapIn" />
+      <wsdl:output message="tns:authenticateSoapOut" />
+    </wsdl:operation>
+    <wsdl:operation name="sendRequestXML">
+      <wsdl:input message="tns:sendRequestXMLSoapIn" />
+      <wsdl:output message="tns:sendRequestXMLSoapOut" />
+    </wsdl:operation>
+    <wsdl:operation name="receiveResponseXML">
+      <wsdl:input message="tns:receiveResponseXMLSoapIn" />
+      <wsdl:output message="tns:receiveResponseXMLSoapOut" />
+    </wsdl:operation>
+    <wsdl:operation name="connectionError">
+      <wsdl:input message="tns:connectionErrorSoapIn" />
+      <wsdl:output message="tns:connectionErrorSoapOut" />
+    </wsdl:operation>
+    <wsdl:operation name="getLastError">
+      <wsdl:input message="tns:getLastErrorSoapIn" />
+      <wsdl:output message="tns:getLastErrorSoapOut" />
+    </wsdl:operation>
+    <wsdl:operation name="closeConnection">
+      <wsdl:input message="tns:closeConnectionSoapIn" />
+      <wsdl:output message="tns:closeConnectionSoapOut" />
+    </wsdl:operation>
+  </wsdl:portType>
+  <wsdl:binding name="QBWebConnectorSvcSoap" type="tns:QBWebConnectorSvcSoap">
+    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" />
+	<!-- this too was added... -->
+	<wsdl:operation name="serverVersion">
+      <soap:operation soapAction="http://developer.intuit.com/serverVersion" style="document" />
+      <wsdl:input>
+        <soap:body use="literal" />
+      </wsdl:input>
+      <wsdl:output>
+        <soap:body use="literal" />
+      </wsdl:output>
+    </wsdl:operation>
+	<wsdl:operation name="clientVersion">
+      <soap:operation soapAction="http://developer.intuit.com/clientVersion" style="document" />
+      <wsdl:input>
+        <soap:body use="literal" />
+      </wsdl:input>
+      <wsdl:output>
+        <soap:body use="literal" />
+      </wsdl:output>
+    </wsdl:operation>
+
+    <wsdl:operation name="authenticate">
+      <soap:operation soapAction="http://developer.intuit.com/authenticate" style="document" />
+      <wsdl:input>
+        <soap:body use="literal" />
+      </wsdl:input>
+      <wsdl:output>
+        <soap:body use="literal" />
+      </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="sendRequestXML">
+      <soap:operation soapAction="http://developer.intuit.com/sendRequestXML" style="document" />
+      <wsdl:input>
+        <soap:body use="literal" />
+      </wsdl:input>
+      <wsdl:output>
+        <soap:body use="literal" />
+      </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="receiveResponseXML">
+      <soap:operation soapAction="http://developer.intuit.com/receiveResponseXML" style="document" />
+      <wsdl:input>
+        <soap:body use="literal" />
+      </wsdl:input>
+      <wsdl:output>
+        <soap:body use="literal" />
+      </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="connectionError">
+      <soap:operation soapAction="http://developer.intuit.com/connectionError" style="document" />
+      <wsdl:input>
+        <soap:body use="literal" />
+      </wsdl:input>
+      <wsdl:output>
+        <soap:body use="literal" />
+      </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="getLastError">
+      <soap:operation soapAction="http://developer.intuit.com/getLastError" style="document" />
+      <wsdl:input>
+        <soap:body use="literal" />
+      </wsdl:input>
+      <wsdl:output>
+        <soap:body use="literal" />
+      </wsdl:output>
+    </wsdl:operation>
+    <wsdl:operation name="closeConnection">
+      <soap:operation soapAction="http://developer.intuit.com/closeConnection" style="document" />
+      <wsdl:input>
+        <soap:body use="literal" />
+      </wsdl:input>
+      <wsdl:output>
+        <soap:body use="literal" />
+      </wsdl:output>
+    </wsdl:operation>
+  </wsdl:binding>
+  <wsdl:service name="QBWebConnectorSvc">
+    <wsdl:port name="QBWebConnectorSvcSoap" binding="tns:QBWebConnectorSvcSoap">
+      <soap:address location="https://idn.vogelfam.net/QBMSDonorSample/QBWebConnectorSvc.asmx" />
+    </wsdl:port>
+  </wsdl:service>
+</wsdl:definitions>
\ No newline at end of file
