? nusoap
Index: uc_eway.recurring.inc
===================================================================
RCS file: /cvs/drupal/contributions/modules/uc_eway/Attic/uc_eway.recurring.inc,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 uc_eway.recurring.inc
--- uc_eway.recurring.inc	21 Oct 2009 03:31:00 -0000	1.1.2.2
+++ uc_eway.recurring.inc	22 Oct 2009 03:41:32 -0000
@@ -8,6 +8,77 @@
  */
 
 /*******************************************************************************
+ * Hooks for Drupal
+ ******************************************************************************/
+
+/**
+ * Implementtion of hook_cron().
+ */
+function uc_eway_cron() {
+  $fail = $success = $pending = 0;
+
+  $fees = uc_eway_recurring_get_fees_for_renew();
+
+  watchdog('uc_eway', 'cron called. got ' . count($fees) . ' fees');
+  if (!empty($fees)) {
+    watchdog('uc_eway', 'got orders with fees');
+    foreach($fees as $fee) {
+      watchdog('uc_eway', 'about to test fee ' . var_export($fee, TRUE));
+      if (!uc_eway_recurring_renew_pending($fee)) {
+        if ($order_id = uc_eway_recurring_renew($fee)) {
+          watchdog('uc_eway', 'fee captured with order id ' . $order_id);
+          $success++;
+        }
+        else {
+          // payment attempted but failed
+          watchdog('uc_eway', 'fee capture failed for fee: ' . var_export($fee, TRUE));
+          $fail++;
+        }
+      }
+      else {
+        watchdog('uc_eway', 'fee is pending: ' . var_export($fee, TRUE));
+        $pending++;
+      }
+    }
+    watchdog('uc_recurring', '@success recurring fees processed successfully; @fail failed; @pending pending', array('@success' => $success, '@fail' => $fail, '@pending' => $pending));
+  }
+
+  watchdog('uc_eway', 'cron exiting uc_eway_cron()');
+}
+
+/*******************************************************************************
+ * Hooks for ubercart
+ ******************************************************************************/
+
+/**
+ * Implementation of hook_uc_checkout_complete().
+ */
+function uc_eway_uc_checkout_complete($order, $account) {
+  $fees = uc_recurring_get_fees($order, TRUE);
+
+  //watchdog('uc_eway', 'order: ' . var_export($order, TRUE) . ', fee: ' . var_export($fees, TRUE));
+  foreach ($fees as $fee) {
+    if ($fee->uid == 0) { // check for anonymous uid
+      $fee->uid = $order->uid;
+      uc_recurring_fee_user_save($fee);
+    }
+    if ($fee->data['eway_rebill_customer_id']) {
+      $customer_id = $fee->data['eway_rebill_customer_id'];
+    }
+  }
+
+  // if the user is newly created we get the eway rebill customer id from
+  // the fee object and save it in the account
+  if (!$account->eway_rebill_customer_id) {
+    //watchdog('uc_eway', 'settings eway_rebill_customer_id for user ' . $account->uid . ' to ' . $customer_id);
+    user_save($account, array(
+      'eway_rebill_customer_id' => $customer_id,
+    ));
+  }
+}
+
+
+/*******************************************************************************
  * Hooks for uc_recurring
  ******************************************************************************/
 
@@ -28,7 +99,7 @@ function uc_eway_recurring_info() {
     'fee handler' => 'eway',
     'payment method' => 'credit',
     'process callback' => 'uc_eway_recurring_process',
-    'renew callback' => 'uc_recurring_eway_renew',
+    'renew callback' => 'uc_eway_recurring_renew',
     'cancel callback' => '_uc_eway_recurring_delete_rebill_event',
     'menu' => array(
       'cancel' => UC_RECURRING_MENU_DEFAULT,
@@ -38,8 +109,60 @@ function uc_eway_recurring_info() {
 }
 
 /**
+ * Implements callback for process
+ */
+function uc_eway_recurring_process($order, &$fee) {
+  // get or create the eway rebill customer id
+  if ($order->uid) {
+    $account = user_load(array('uid' => $order->uid));
+    watchdog('uc_eway', 'Order has user: ' . var_export($account, TRUE));
+
+    // is this user already a rebill customer?
+    if (!$account->eway_rebill_customer_id) {
+      $customer_id = _uc_eway_recurring_create_rebill_customer($order);
+    }
+
+    user_save($account, array(
+      'eway_rebill_customer_id' => $customer_id,
+    ));
+  }
+  else {
+    // anonymous user in checkout and user hasn't been created yet.
+    // store the rebill customer id in the fee for now, we'll add it
+    // to the user object in hook_uc_checkout_complete()
+    $customer_id = _uc_eway_recurring_create_rebill_customer($order);
+
+    watchdog('uc_eway', 'Order has no user yet.');
+  }
+
+  if (!$customer_id) {
+    return FALSE;
+  }
+
+  // set the customer id in the fee object to be saved in checkout_complete()
+  $fee->data['eway_rebill_customer_id'] = $customer_id;
+
+  // create a rebill event
+  $result = _uc_eway_recurring_create_rebill_event($order, $fee);
+
+  if ($result['error']) {
+    watchdog('uc_eway', t('Failed to create Rebill Event: ' . var_export($result, TRUE)));
+    return FALSE;
+  }
+  else {
+    //watchdog('uc_eway_recurring', t('Created Rebill Event: ' . $result['RebillID']));
+    $fee->fee_handler = 'eway';
+    $fee->own_handler = TRUE;
+    $fee->data['rebill_id'] = $result['RebillID'];
+
+    return TRUE;
+  }
+}
+
+/**
  * Implements callback uc_recurring_[payment_method]_fee()
  */
+/*
 function uc_eway_recurring_process($order, &$fee) {
   $account = user_load(array('uid' => $order->uid));
 
@@ -71,10 +194,12 @@ function uc_eway_recurring_process($orde
     return TRUE;
   }
 }
+*/
 
 /**
  * Implements callback uc_recurring_[fee_handler]_renew()
  */
+/*
 function uc_recurring_eway_renew($order, $fee) {
   $account = user_load(array('uid' => $order->uid));
 
@@ -95,10 +220,83 @@ function uc_recurring_eway_renew($order,
     return FALSE;
   }
 }
+*/
+
+/**
+ * Renew callback
+ */
+function uc_eway_recurring_renew($fee) {
+  global $user;
+  $order = uc_order_load($fee->order_id);
+  $old_id = $order->order_id;
+
+  // Create a new order by cloning the current order and replacing order ID.
+  $new_order = uc_order_new($order->uid, 'in_checkout');
+  $new_id = $new_order->order_id;
+
+  $new_order = $order;
+  $new_order->order_id = $new_id;
+
+  // Set a single product - the recurring fee.
+  $product = new stdClass();
+  $product->order_id = $new_id;
+  $product->nid = $fee->data['nid'];
+  $product->model = $fee->data['model'];
+  $product->title = !empty($fee->fee_title) ? $fee->fee_title : t('Renewal of product @model', array('@model' => $product->model));
+  $product->qty = 1;
+  $product->price = $fee->fee_amount;
+
+  // initialize these items to remove warnings
+  $product->cost = 0;
+  $product->manufacturer = '';
+  $product->weight = 0;
+  $product->data = array();
+
+  // Add a flag that this order is a recurring fee order, so it won't be
+  // processed by uc_recurring_process_order().
+  $product->data['recurring_fee'] = TRUE;
+  $new_order->products = array($product);
+
+  // Give other modules a chance to modify the new order before processing
+  //module_invoke_all('recurring_renew', $new_order, $fee);
+  uc_order_update_status($new_id, 'processing');
+
+  //if (uc_recurring_invoke($fee->fee_handler, 'renew callback', array($new_order, &$fee))) {
+  //watchdog('uc_eway', 'trying to renew fee: ' . var_export($fee, TRUE));
+  if (uc_eway_recurring_renew_query($fee)) {
+    uc_order_save($new_order);
+
+    // Add a comment in the old and new order history.
+    uc_order_comment_save($old_id, $user->uid, t('New recurring fee processed, new order is <a href="@store-orders">@order_id</a>.', array('@store-orders' => url('admin/store/orders/'.$new_id), '@order_id' => $new_id)));
+    uc_order_comment_save($new_id, $user->uid, t('Order created as a recurring fee for order <a href="@store-orders">@order_id</a>.', array('@store-orders' => url('admin/store/orders/'.$old_id), '@order_id' => $old_id)));
+
+    // Set new intervals.
+    uc_recurring_set_intervals($fee);
+    // Add the new order ID to the fee object.
+    $fee->data['recurring orders'][$new_id] = $new_id;
+    // Save the fee object.
+    uc_recurring_fee_user_save($fee);
+    // Return the new order ID.
+    return $new_id;
+  }
+  else {
+    // Charging failed.
+    uc_recurring_process_extensions($order, $fee);
+
+    uc_order_comment_save($fee->order_id, $user->uid, t('Error: Recurring fee <a href="@orders-recurring-view">@fee</a> for product @model failed.', array('@orders-recurring-view' => url('admin/store/orders/recurring/view/fee/'. $fee->rfid), '@fee' => $fee->rfid, '@model' => $fee->data['model'])));
+    watchdog('uc_eway', 'Failed to capture recurring fee of @amount for product @model on order @order_id.', array('@amount' => $fee->fee_amount, '@model' => $fee->data['model'], '@order_id' => $fee->order_id), WATCHDOG_ERROR, l(t(
+'order !order_id', array('!order_id' => $fee->order_id)), 'admin/store/orders/'. $fee->order_id));
+
+    module_invoke_all('recurring_api', 'fail', $fee);
+    uc_order_delete($new_id);
+    return FALSE;
+  }
+}
 
 /**
  * Implements *optional* callback uc_recurring_[fee_handler]_renew_pending()
  */
+/*
 function uc_recurring_eway_renew_pending($fee) {
   $account = user_load(array('uid' => $fee->uid));
   $result = _uc_eway_recurring_query_rebill_transactions($fee, $account);
@@ -118,6 +316,7 @@ function uc_recurring_eway_renew_pending
     return FALSE;
   }
 }
+*/
 
 /**
  * Implementation of hook_recurring_user_delete().
@@ -132,6 +331,66 @@ function uc_eway_recurring_user_delete($
  ******************************************************************************/
 
 /**
+ * Check rebill event status
+ */
+function uc_eway_recurring_renew_query($fee) {
+  $account = user_load(array('uid' => $fee->uid));
+  $result = _uc_eway_recurring_query_rebill_transactions($fee, $account);
+
+  // get all transactions, test if this fee went through
+  if (isset($result['Successful']['QueryTransactionsResult']['rebillTransaction'])) {
+    watchdog('uc_eway', t('Renew charged for fee: ' . var_export($fee, TRUE) . ', Transaction status is SUCCESSFUL: ' . var_export($result['Successful'], TRUE)));
+    return TRUE;
+  }
+  elseif (isset($result['Failed']['QueryTransactionsResult']['rebillTransaction'])) {
+    watchdog('uc_eway', t('Renew failed for fee: ' . var_export($fee, TRUE) . ', Transaction status is FAILED: ' . var_export($result['Failed'], TRUE)));
+    return FALSE;
+  }
+  else {
+    // something went very wrong
+    watchdog('uc_eway', t('eWAY returned nonsense for fee: ' . var_export($fee, TRUE) . ', SOAP response: ' . var_export($result, TRUE)));
+    return FALSE;
+  }
+}
+
+/**
+ * Check if a rebill event has been processed by eWay
+ */
+function uc_eway_recurring_renew_pending($fee) {
+  $account = user_load(array('uid' => $fee->uid));
+  
+  $result = _uc_eway_recurring_query_rebill_transactions($fee, $account);
+
+  //watchdog('uc_eway_recurring', 'uc_recurring_eway_renew_fee(): ' . var_export($result, TRUE));
+  
+  if (isset($result['Future']['QueryTransactionsResult']['rebillTransaction'])) {
+    //watchdog('uc_eway_recurring', 'FUTURE!');
+    return TRUE;
+  }
+  elseif (isset($result['Pending']['QueryTransactionsResult']['rebillTransaction'])) {
+    //watchdog('uc_eway_recurring', 'PENDING!');
+    return TRUE;
+  }
+  else {
+    //watchdog('uc_eway_recurring', 'returning FALSE!');
+    return FALSE;
+  }
+}
+
+/**
+ * Get all pending fees that should be renewed.
+ */
+function uc_eway_recurring_get_fees_for_renew() {
+  $fees= array();
+  $result = db_query("SELECT * FROM {uc_recurring_users} WHERE remaining_intervals <> 0 AND next_charge <= %d AND fee_handler = 'eway' ORDER BY order_id DESC", time());
+  while ($fee = db_fetch_object($result)) {
+    $fee->data = unserialize($fee->data);
+    $fees[$fee->rfid] = $fee;
+  }
+  return $fees;
+}
+
+/**
  * Returns the path of the NuSOAP library
  */
 function uc_eway_recurring_nusoap_path() {
@@ -167,34 +426,6 @@ function _uc_eway_recurring_soap_call($o
   return $result;
 }
 
-// DEBUG TIME FUNCTION
-function _time($type = 'none') {
-  return time();
-  switch($type) {
-    case 'uc_recurring_fee':
-      $hour = 7;
-      $minute = 0;
-      $second = 0;
-      $month = 6;
-      $day = 27;
-      $year = 2009;
-      break;
-    case 'uc_recurring_renew':
-      $hour = 7;
-      $minute = 1;
-      $second = 0;
-      $month = 6;
-      $day = 27;
-      $year = 2009;
-      break;
-    default:
-      return time();
-  }
-
-  $time = mktime($hour, $minute, $second, $month, $day, $year);
-  return $time;
-}
-
 /**
  * Create Rebill Customer
  */
@@ -226,9 +457,12 @@ function _uc_eway_recurring_create_rebil
 
   $response = _uc_eway_recurring_soap_call('CreateRebillCustomer', $data);
   if ($response['CreateRebillCustomerResult']['Result'] == 'Success') {
+    return $response['CreateRebillCustomerResult']['RebillCustomerID'];
+    /*
     $account = user_save($account, array(
       'eway_rebill_customer_id' => $response['CreateRebillCustomerResult']['RebillCustomerID'],
     ));
+    */
   }
 
   return $account;
@@ -255,6 +489,89 @@ function _uc_eway_recurring_delete_rebil
 /**
  * Create Rebill Event
  */
+function _uc_eway_recurring_create_rebill_event($order, $fee) {
+  // create invoice description
+  $description = '';
+  if (is_array($order->products)) {
+    foreach ($order->products as $product) {
+      if (!empty($description)) {
+        $description .= ' / ';
+      }
+      $description .= $product->qty . 'x ' . $product->title . ' ';
+      if (is_array($product->data['attributes'])) {
+        foreach ($product->data['attributes'] as $key => $value) {
+          $description .= ', '. $key .': '. $value;
+        }
+      }
+    }
+  }
+
+  $cc_name = strlen($order->payment_details['cc_name']) ? $order->payment_details['cc_name'] : $order->billing_first_name . ' ' . $order->billing_last_name;
+
+  // get data from uc_recurring -> eway rebill format
+  $initial_charge = split(' ', $fee->initial_charge);
+  if ((int)$initial_charge[0] === 0) {
+    $init_fee = (int)$fee->fee_amount * 100;
+  }
+  else {
+    $init_fee = 0;
+  }
+
+  // pretend now is GMT + 12 as eway will complain if we're behind AEST
+  $now = gmdate('U', time() + 3600 * 12);
+
+  $regular_interval = split(' ', $fee->regular_interval);
+  $start_timestamp = strtotime('+' . $fee->regular_interval, $now);
+  switch($regular_interval[1]) {
+    case 'days': $interval_type = 1; break;
+    case 'weeks': $interval_type = 2; break;
+    case 'months': $interval_type = 3; break;
+    case 'years': $interval_type = 4; break;
+  }
+  if ($fee->number_intervals) {
+    $end_date = date('d/m/Y', strtotime('+' . $regular_interval[0] * $fee->number_intervals . ' ' . $regular_interval[1], $now));
+  }
+  else {
+    $end_date = UC_EWAY_RECURRING_VAST_END_DATE;
+  }
+
+  $data = array(
+    'RebillCustomerID' => $fee->data['eway_rebill_customer_id'],
+    'RebillInvRef' => $order->order_id,
+    'RebillInvDes' => substr($description, 0, 10000),
+    'RebillCCName' => $cc_name,
+    'RebillCCNumber' => $order->payment_details['cc_number'],
+    'RebillCCExpMonth' => $order->payment_details['cc_exp_month'],
+    'RebillCCExpYear' => $order->payment_details['cc_exp_year'],
+    'RebillInitAmt' => $init_fee,
+    'RebillInitDate' => date('d/m/Y', $now),
+    'RebillRecurAmt' => (int)$fee->fee_amount * 100,
+    'RebillStartDate' => date('d/m/Y', $start_timestamp),
+    'RebillInterval' => $regular_interval[0],
+    'RebillIntervalType' => $interval_type,
+    'RebillEndDate' => $end_date,
+  );
+
+  $response = _uc_eway_recurring_soap_call('CreateRebillEvent', $data);
+
+  if ($response['CreateRebillEventResult']['Result'] == 'Success') {
+    return array(
+      'error' => 0,
+      'RebillID' => $response['CreateRebillEventResult']['RebillID'],
+    );
+  }
+  else {
+    return array(
+      'error' => 1,
+      'ErrorDetails' => $response['CreateRebillEventResult']['ErrorDetails'],
+    );
+  }
+}
+
+/**
+ * Create Rebill Event
+ */
+/*
 function _uc_eway_recurring_create_rebill_event($order, $fee, $account) {
   // create invoice description
   $description = '';
@@ -324,6 +641,7 @@ function _uc_eway_recurring_create_rebil
     );
   }
 }
+*/
 
 /**
  * Update Rebill Event
