diff --git a/payment/uc_google_checkout/uc_google_checkout.module b/payment/uc_google_checkout/uc_google_checkout.module
index 49f28ef..ef07377 100644
--- a/payment/uc_google_checkout/uc_google_checkout.module
+++ b/payment/uc_google_checkout/uc_google_checkout.module
@@ -108,7 +108,7 @@ function uc_google_checkout_init() {
   global $user;
   $users = variable_get('uc_google_checkout_order_users', array());
   if (isset($users[$user->uid])) {
-    unset($_SESSION['cart_order'], $_SESSION['do_complete'], $_SESSION['new_user'], $users[$user->uid]);
+    unset($_SESSION['cart_order'], $_SESSION['do_complete'], $users[$user->uid]);
     variable_set('uc_google_checkout_order_users', $users);
   }
 
diff --git a/payment/uc_payment/uc_payment.ca.inc b/payment/uc_payment/uc_payment.ca.inc
index a69160f..bb02213 100644
--- a/payment/uc_payment/uc_payment.ca.inc
+++ b/payment/uc_payment/uc_payment.ca.inc
@@ -20,7 +20,7 @@ function uc_payment_ca_predicate() {
   // Set the order status to "Payment Received" when a payment is received
   // and the balance is less than or equal to 0.
   $predicates['uc_payment_received'] = array(
-    '#title' => t('Update order status on full payment'),
+    '#title' => t('Update order status to payment received before checkout'),
     '#description' => t('Only happens when a payment is entered and the balance is <= $0.00.'),
     '#class' => 'payment',
     '#trigger' => 'uc_payment_entered',
@@ -40,14 +40,13 @@ function uc_payment_ca_predicate() {
           ),
         ),
         array(
-          '#name' => 'uc_order_status_condition',
-          '#title' => t('If the order status is not already Payment Received.'),
+          '#name' => 'uc_order_state_condition',
+          '#title' => t('If the order state is in checkout.'),
           '#argument_map' => array(
             'order' => 'order',
           ),
           '#settings' => array(
-            'negate' => TRUE,
-            'order_status' => 'payment_received',
+            'order_state' => 'in_checkout',
           ),
         ),
       ),
@@ -66,10 +65,129 @@ function uc_payment_ca_predicate() {
     ),
   );
 
+  // Set the order status to "Completed" when a payment is received
+  // and the balance is less than or equal to 0 and the order is shippable
+  // This conditional action will work if the order is pending/processing
+  // which is set when the checkout is completed
+  $predicates['uc_payment_received_after_checkout_not_shippable'] = array(
+    '#title' => t('Complete non-shippable order on full payment after checkout'),
+    '#description' => t('Only happens when a payment is entered after checkout and the balance is <= $0.00.'),
+    '#class' => 'payment',
+    '#trigger' => 'uc_payment_entered',
+    '#status' => 1,
+    "#weight" => 2,
+    '#conditions' => array(
+      '#operator' => 'AND',
+      '#conditions' => array(
+        array(
+          '#name' => 'uc_payment_condition_order_balance',
+          '#title' => t('If the balance is less than or equal to $0.00.'),
+          '#argument_map' => array(
+            'order' => 'order',
+          ),
+          '#settings' => array(
+            'negate' => FALSE,
+            'balance_comparison' => 'less_equal',
+          ),
+        ),
+        array(
+          '#name' => 'uc_order_condition_is_shippable',
+          '#title' => t('If the order is not shippable.'),
+          '#argument_map' => array(
+            'order' => 'order',
+          ),
+          '#settings' => array(
+            'negate' => TRUE,
+          ),
+        ),
+        array(
+          '#name' => 'uc_order_state_condition',
+          '#title' => t('If the order state is in post checkout.'),
+          '#argument_map' => array(
+            'order' => 'order',
+          ),
+          '#settings' => array(
+            'order_state' => 'post_checkout',
+          ),
+        ),
+      ),
+    ),
+    '#actions' => array(
+      array(
+        '#name' => 'uc_order_update_status',
+        '#title' => t('Update the order status to Completed.'),
+        '#argument_map' => array(
+          'order' => 'order',
+        ),
+        '#settings' => array(
+          'order_status' => 'completed',
+        ),
+      ),
+    ),
+  );
+
+  // Set the order status to "Payment received" when a payment is received
+  // and the balance is less than or equal to 0 and the order is shippable
+  // This conditional action will work if the order is pending/processing
+  // which is set when the checkout is completed
+  $predicates['uc_payment_received_after_checkout_shippable'] = array(
+    '#title' => t('Update shippable order status to payment received after checkout'),
+    '#description' => t('Only happens when a payment is entered after checkout and the balance is <= $0.00.'),
+    '#class' => 'payment',
+    '#trigger' => 'uc_payment_entered',
+    '#status' => 1,
+    "#weight" => 1,
+    '#conditions' => array(
+      '#operator' => 'AND',
+      '#conditions' => array(
+        array(
+          '#name' => 'uc_payment_condition_order_balance',
+          '#title' => t('If the balance is less than or equal to $0.00.'),
+          '#argument_map' => array(
+            'order' => 'order',
+          ),
+          '#settings' => array(
+            'negate' => FALSE,
+            'balance_comparison' => 'less_equal',
+          ),
+        ),
+        array(
+          '#name' => 'uc_order_condition_is_shippable',
+          '#title' => t('If the order is shippable.'),
+          '#argument_map' => array(
+            'order' => 'order',
+          ),
+        ),
+        array(
+          '#name' => 'uc_order_state_condition',
+          '#title' => t('If the order state is in post checkout.'),
+          '#argument_map' => array(
+            'order' => 'order',
+          ),
+          '#settings' => array(
+            'order_state' => 'post_checkout',
+          ),
+        ),
+      ),
+    ),
+    '#actions' => array(
+      array(
+        '#name' => 'uc_order_update_status',
+        '#title' => t('Update the order status to Completed.'),
+        '#argument_map' => array(
+          'order' => 'order',
+        ),
+        '#settings' => array(
+          'order_status' => 'payment_received',
+        ),
+      ),
+    ),
+  );
+
   // Set the order status to "Completed" when checkout is complete, none
   // of the products are shippable, and the balance is less than or equal to 0.
   $predicates['uc_checkout_complete_paid'] = array(
-    '#title' => t('Update order status upon checkout completion with full payment'),
+    '#title' => t('Complete non-shippable order status on full payment on checkout'),
     '#trigger' => 'uc_checkout_complete',
     '#class' => 'payment',
     '#status' => 1,
@@ -98,6 +216,17 @@ function uc_payment_ca_predicate() {
             'negate' => TRUE,
           ),
         ),
+        array(
+          '#name' => 'uc_order_status_condition',
+          '#title' => t('If the order status is not already completed.'),
+          '#argument_map' => array(
+            'order' => 'order',
+          ),
+          '#settings' => array(
+            'negate' => TRUE,
+            'order_status' => 'completed',
+          ),
+        ),
       ),
     ),
     '#actions' => array(
diff --git a/uc_cart/uc_cart.admin.inc b/uc_cart/uc_cart.admin.inc
index 7fc865c..1796726 100644
--- a/uc_cart/uc_cart.admin.inc
+++ b/uc_cart/uc_cart.admin.inc
@@ -537,6 +537,19 @@ function uc_cart_checkout_messages_form() {
   );
   $form['checkout_messages']['uc_msg_order_new_user_format'] = filter_form(variable_get('uc_msg_order_new_user_format', FILTER_FORMAT_DEFAULT), NULL, array('uc_msg_order_new_user_format'));
 
+  $form['checkout_messages']['uc_msg_order_new_user_logged_in'] = array(
+    '#type' => 'textarea',
+    '#title' => t('Checkout completion for new logged in users'),
+    '#description' => t('Message displayed upon checkout for a new user whose account was just created and also <em>"Login users when new customer accounts are created at checkout."</em> is set on the <a href="!user_login_setting_ur">checkout settings</a>. <a href="!url">Uses order and global tokens</a>.', array('!url' => url('admin/store/help/tokens'), '!user_login_setting_ur' => 'admin/store/settings/checkout/edit/basic')),
+    '#summary' => variable_get('uc_msg_order_new_user_logged_in', uc_get_message('completion_new_user_logged_in'))
+               ? t('Completion text for new logged in users is set.')
+               : t('Completion text for new logged in users is not set.'),
+    '#default_value' => variable_get('uc_msg_order_new_user_logged_in', uc_get_message('completion_new_user_logged_in')),
+    '#rows' => 3,
+  );
+  $form['checkout_messages']['uc_msg_order_new_user_logged_in_format'] = filter_form(variable_get('uc_msg_order_new_user_logged_in_format', FILTER_FORMAT_DEFAULT), NULL, array('uc_msg_order_new_user_logged_in_format'));
+
+
   $form['uc_msg_continue_shopping'] = array(
     '#type' => 'textarea',
     '#title' => t('Continue shopping message'),
diff --git a/uc_cart/uc_cart.module b/uc_cart/uc_cart.module
index 450089a..8e07c3d 100644
--- a/uc_cart/uc_cart.module
+++ b/uc_cart/uc_cart.module
@@ -756,7 +756,8 @@ function uc_cart_uc_message() {
   $messages['completion_message'] = t('Your order is complete! Your order number is [order-id].');
   $messages['completion_logged_in'] = t('Thank you for shopping at [store-name]. While logged in, you may continue shopping or <a href="[order-url]">view your current order status</a> and order history.');
   $messages['completion_existing_user'] = t("Thank you for shopping at [store-name]. Your current order has been attached to the account we found matching your e-mail address.\n\n<a href=\"!user_url\">Login</a> to view your current order status and order history. Remember to login when you make your next purchase for a faster checkout experience!", array('!user_url' => url('user')));
-  $messages['completion_new_user'] = t("Thank you for shopping at [store-name]. A new account has been created for you here that you may use to view your current order status.\n\n<a href=\"!user_url\">Login</a> to your new account using the following information:\n\n<strong>Username:</strong> !new_username\n<strong>Password:</strong> !new_password", array('!user_url' => url('user')));
+  $messages['completion_new_user'] = t("Thank you for shopping at [store-name]. A new account has been created for you here that you may use to view your current order status.\n\nYour password and further instructions have been sent to your e-mail address.");
+  $messages['completion_new_user_logged_in'] = t("Thank you for shopping at [store-name]. A new account has been created for you here that you may use to view your current order status.\n\nYour password and further instructions have been sent to your e-mail address.\n\nFor your convenience, you are already logged in with your newly created account.");
   $messages['continue_shopping'] = t('<a href="[site-url]">Return to the front page.</a>');
 
   return $messages;
@@ -1187,6 +1188,14 @@ function uc_cart_continue_shopping_url($unset = TRUE) {
 function uc_cart_complete_sale($order, $login = FALSE) {
   global $user;
 
+  // Get current serialized data from the order database, we use this instead of
+  // the $order object because we store data on the database directly in this
+  // function which can be executed more than once.
+  $order->data = unserialize(db_result(db_query("SELECT data FROM {uc_orders} WHERE order_id = %d", $order->order_id)));
+
+  // check to see if this function has been already run, if so, just retrieve the
+  // necessary information from the database
+  if (empty($order->data['complete_sale'])) {
   // Logic to create new user if necessary:
   if ($order->uid == 0) {
     // Check for an existing user account with the e-mail address from checkout.
@@ -1200,20 +1209,12 @@ function uc_cart_complete_sale($order, $login = FALSE) {
       $message_type = 'existing_user';
     }
     else {
-      // Get a valid new username.
-      if (empty($order->data['new_user']['name'])) {
-        $name = uc_store_email_to_username($order->primary_email);
-      }
-      else {
-        $name = $order->data['new_user']['name'];
-      }
-
       // Setup the account fields array and save it as a new user.
       $fields = array(
-        'name' => $name,
+        'name' => uc_store_email_to_username($order->primary_email),
         'mail' => $order->primary_email,
         'init' => $order->primary_email,
-        'pass' => empty($order->data['new_user']['pass']) ? user_password(variable_get('uc_pwd_length', 6)) : $order->data['new_user']['pass'],
+        'pass' => user_password(variable_get('uc_pwd_length', 6)),
         'roles' => array(),
         'status' => variable_get('uc_new_customer_status_active', TRUE) ? 1 : 0,
       );
@@ -1229,18 +1230,11 @@ function uc_cart_complete_sale($order, $login = FALSE) {
       }
 
       // Store the login details in the session for use on the page display.
-      $_SESSION['new_user'] = array('name' => $fields['name'], 'pass' => $fields['pass']);
+        $order->data['complete_sale']['new_user'] = array('name' => $fields['name']);
 
       // Update the order's uid in this request and in the database.
       $order->uid = $account->uid;
-      unset($order->data['new_user']['pass']);
-      db_query("UPDATE {uc_orders} SET uid = %d, data = '%s' WHERE order_id = %d", $order->uid, serialize($order->data), $order->order_id);
-
-      // Login the user if specified.
-      if ($login) {
-        $form_state = array('values' => $fields);
-        drupal_execute('user_login', $form_state);
-      }
+        db_query("UPDATE {uc_orders} SET uid = %d WHERE order_id = %d", $order->uid, $order->order_id);
 
       $message_type = 'new_user';
     }
@@ -1256,12 +1250,51 @@ function uc_cart_complete_sale($order, $login = FALSE) {
     }
   }
 
+    // Store complete_sale order data
+    $order->data['complete_sale']['message_type'] = $message_type;
+
+    // Move an order's status from "In Checkout" to "Pending"
+    $status = db_result(db_query("SELECT order_status FROM {uc_orders} WHERE order_id = %d", $order->order_id));
+    if (uc_order_status_data($status, 'state') == 'in_checkout') {
+      $status = uc_order_state_default('post_checkout');
+      if (uc_order_update_status($order->order_id, $status)) {
+        $order->order_status = $status;
+      }
+    }
+
+    // invoke the checkout complete CA trigger
+    module_invoke_all('uc_checkout_complete', $order, $account);
+    ca_pull_trigger('uc_checkout_complete', $order, $account);
+
+    // Update the order's data in the database.
+    db_query("UPDATE {uc_orders} SET data = '%s' WHERE order_id = %d", serialize($order->data), $order->order_id);
+  }
+  else {
+    $message_type = $order->data['complete_sale']['message_type'];
+
+    // Also load back the order uid from the database, as with the complete_sale
+    // information, this can be stored in a previous execution of this function
+    // w/o yet being available to the order object
+     $order->uid = db_result(db_query("SELECT uid FROM {uc_orders} WHERE order_id = %d", $order->order_id));
+  }
+
+  // Login the user if specified, we assume that at this point, $order->uid has
+  // to be valid
+  if ($message_type == 'new_user' && $login && $order->uid && $user->uid == 0) {
+    $message_type = 'new_user_logged_in';
+    // As we might not have the password available the user creation was actually
+    // made before by a previous run to this function, as it may be the case
+    // with paypal or other notification based payment methods, we just
+    // forcley log in the user, which will have the same effect without the
+    // need to have the password
+    $user = user_load($order->uid);
+  }
+
   $messages = array();
   $messages['uc_msg_order_submit_format'] = variable_get('uc_msg_order_submit', uc_get_message('completion_message'));
   if ($message = variable_get('uc_msg_order_'. $message_type, uc_get_message('completion_'.$message_type))) {
-    if (isset($_SESSION['new_user'])) {
-      $variables['!new_username'] = check_plain($_SESSION['new_user']['name']);
-      $variables['!new_password'] = check_plain($_SESSION['new_user']['pass']);
+    if (isset($order->data['complete_sale']['new_user'])) {
+      $variables['!new_username'] = check_plain($order->data['complete_sale']['new_user']['name']);
       $messages['uc_msg_order_'. $message_type .'_format'] = strtr($message, $variables);
     }
     else {
@@ -1278,23 +1311,17 @@ function uc_cart_complete_sale($order, $login = FALSE) {
   }
   $themed_output = theme('uc_cart_complete_sale', $output_message, $order);
 
-  // Move an order's status from "In Checkout" to "Pending"
-  $status = db_result(db_query("SELECT order_status FROM {uc_orders} WHERE order_id = %d", $order->order_id));
-  if (uc_order_status_data($status, 'state') == 'in_checkout') {
-    $status = uc_order_state_default('post_checkout');
-    if (uc_order_update_status($order->order_id, $status)) {
-      $order->order_status = $status;
-    }
-  }
-
   // Empty that cart...
   uc_cart_empty(uc_cart_get_id(FALSE), 'checkout');
 
-  module_invoke_all('uc_checkout_complete', $order, $account);
-  ca_pull_trigger('uc_checkout_complete', $order, $account);
-
   // Clear our the session variables used to force the cart workflow.
-  unset($_SESSION['cart_order'], $_SESSION['do_complete'], $_SESSION['new_user']);
+  // @TODO: As there is no way to clear session variables from a different
+  // session (as within a payment method's callback that inits a new session
+  // This information should not really be stored in the session element.
+  // I think the best idea is to have an ubercart session table, keyed by
+  // session id. In that way, we can pass the session id to the payment methods,
+  // have it back from it on the callback and clear the sessions vars there.
+  unset($_SESSION['cart_order'], $_SESSION['do_complete']);
 
   return $themed_output;
 }
diff --git a/uc_order/templates/uc_order-customer.tpl.php b/uc_order/templates/uc_order-customer.tpl.php
index c052642..5a0006a 100644
--- a/uc_order/templates/uc_order-customer.tpl.php
+++ b/uc_order/templates/uc_order-customer.tpl.php
@@ -39,10 +39,8 @@
             <?php if ($thank_you_message) { ?>
             <p><b><?php echo t('Thanks for your order, !order_first_name!', array('!order_first_name' => $order_first_name)); ?></b></p>
 
-            <?php if (isset($_SESSION['new_user'])) { ?>
-            <p><b><?php echo t('An account has been created for you with the following details:'); ?></b></p>
-            <p><b><?php echo t('Username:'); ?></b> <?php echo $new_username; ?><br />
-            <b><?php echo t('Password:'); ?></b> <?php echo $new_password; ?></p>
+            <?php if (isset($order->data['complete_sale']['new_user'])) { ?>
+            <p><b><?php echo t('A new account has been created for you here that you may use to view your current order status. Your password and further instructions have been sent to you on a separate email.'); ?></b></p>
             <?php } ?>
 
             <p><b><?php echo t('Want to manage your order online?'); ?></b><br />
diff --git a/uc_order/uc_order.ca.inc b/uc_order/uc_order.ca.inc
index 7ce5aa0..6843381 100644
--- a/uc_order/uc_order.ca.inc
+++ b/uc_order/uc_order.ca.inc
@@ -128,6 +128,16 @@ function uc_order_ca_condition() {
     ),
   );
 
+  $conditions['uc_order_state_condition'] = array(
+    '#title' => t('Check the order state'),
+    '#description' => t('Returns TRUE if the current order status belong to the order state specified below.'),
+    '#category' => t('Order'),
+    '#callback' => 'uc_order_condition_check_order_state',
+    '#arguments' => array(
+      'order' => $order_arg,
+    ),
+  );
+
   $conditions['uc_order_condition_total'] = array(
     '#title' => t('Check the order total'),
     '#description' => t('Returns TRUE if the current order total is within the parameters below.'),
@@ -368,6 +378,36 @@ function uc_order_condition_check_order_status_form($form_state, $settings = arr
 }
 
 /**
+ * Check the current order state.
+ *
+ * @see uc_order_condition_check_order_state_form()
+ */
+function uc_order_condition_check_order_state($order, $settings) {
+  // Return TRUE if the order status matches.
+  return uc_order_status_data($order->order_status, 'state') == $settings['order_state'];
+}
+
+/**
+ * @see uc_order_condition_check_order_state()
+ */
+function uc_order_condition_check_order_state_form($form_state, $settings = array()) {
+  foreach (uc_order_state_list('general') as $state) {
+    $options[$state['id']] = $state['title'];
+  }
+  foreach (uc_order_state_list('specific') as $state) {
+    $options[$state['id']] = $state['title'];
+  }
+  $form['order_state'] = array(
+    '#type' => 'select',
+    '#title' => t('Order state'),
+    '#options' => $options,
+    '#default_value' => $settings['order_state'],
+  );
+
+  return $form;
+}
+
+/**
  * Check the current order balance.
  *
  * @see uc_order_condition_total_form()
diff --git a/uc_order/uc_order.module b/uc_order/uc_order.module
index 2c5a71b..6001152 100644
--- a/uc_order/uc_order.module
+++ b/uc_order/uc_order.module
@@ -365,13 +365,11 @@ function uc_order_token_values($type, $object = NULL) {
     case 'order':
       $order = $object;
 
-      if (isset($_SESSION['new_user']) && is_array($_SESSION['new_user'])) {
-        $values['new-username'] = check_plain($_SESSION['new_user']['name']);
-        $values['new-password'] = check_plain($_SESSION['new_user']['pass']);
+      if (isset($order->data['complete_sale']['new_user']) && is_array($order->data['complete_sale']['new_user'])) {
+        $values['new-username'] = check_plain($order->data['complete_sale']['new_user']['name']);
       }
       else {
         $values['new-username'] = '';
-        $values['new-password'] = '';
       }
       $values['order-id'] = $order->order_id;
       $values['order-uid'] = $order->uid;
@@ -443,7 +441,6 @@ function uc_order_token_list($type = 'all') {
 
   if ($type == 'order' || $type == 'ubercart' || $type == 'all') {
     $tokens['order']['new-username'] = t('New username associated with an order if applicable.');
-    $tokens['order']['new-password'] = t('New password associated with an order if applicable.');
     $tokens['order']['order-id'] = t('The order ID.');
     $tokens['order']['order-uid'] = t('The user ID of the order.');
     $tokens['order']['order-url'] = t('The URL to the order');
