? uc_recurring-authorize-580938-4.patch
Index: uc_recurring.uc_authorizenet.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/uc_recurring/modules/Attic/uc_recurring.uc_authorizenet.inc,v
retrieving revision 1.1.2.6
diff -u -p -r1.1.2.6 uc_recurring.uc_authorizenet.inc
--- uc_recurring.uc_authorizenet.inc	17 Sep 2009 01:08:46 -0000	1.1.2.6
+++ uc_recurring.uc_authorizenet.inc	23 Sep 2009 00:01:46 -0000
@@ -40,7 +40,18 @@ function uc_recurring_uc_authorizenet_re
     'payment method' => 'credit',
     'module' => 'uc_recurring',
     'fee handler' => 'authorizenet_arb',
-    'process' => 'uc_recurring_authorizenet_arb_process',
+    'process callback' => 'uc_recurring_authorizenet_arb_process',
+    'renew callback' => 'uc_recurring_authorizenet_arb_renew',
+    'cancel callback' => 'uc_recurring_authorizenet_arb_cancel',
+    'menu' => array(
+      'edit' => UC_RECURRING_MENU_DEFAULT,
+      'update' => array(
+        'title' => 'Update Account Details',
+        'page arguments' => array('uc_recurring_authorizenet_arb_update_form'),
+        'file' => 'modules/uc_recurring.uc_authorizenet.inc',
+      ),
+      'cancel' => UC_RECURRING_MENU_DEFAULT,
+    ),
     'own handler' => TRUE,
   );
 
@@ -49,7 +60,7 @@ function uc_recurring_uc_authorizenet_re
   }
   elseif (variable_get('uc_authnet_arb_mode', 'disabled') != 'disabled') {
     // ARB not currently supported, uncomment to test
-    // $items['authorizenet'] = $items['authorizenet_arb'];
+    $items['authorizenet'] = $items['authorizenet_arb'];
   }
   return $items;
 }
@@ -271,8 +282,8 @@ function uc_recurring_authorizenet_arb_p
           'length' => $length,
           'unit' => $unit,
         ),
-        'startDate' => date('Y-m-d', strtotime('+ '. $fee->initial_charge)),
-        'totalOccurrences' => $fee->number_intervals,
+        'startDate' => date('Y-m-d', $fee->next_charge),
+        'totalOccurrences' => $fee->remaining_intervals == -1 ? 9999 : $fee->remaining_intervals,
         'trialOccurrences' => '0',
       ),
       'amount' => round($fee->fee_amount, 2),
@@ -348,7 +359,139 @@ function uc_recurring_authorizenet_arb_p
     uc_order_comment_save($order->order_id, 0, t('Authorize.Net: Recurring fee for @model failed.<br />@error - @text', array('@model' => $fee->model, '@error' => $data['code'], '@text' => $data['text'])), 'admin');
     return FALSE;
   }
+  uc_order_comment_save($order->order_id, 0, t('Authorize.Net: ARB subscription created - @id', array('@id' => $data['subscriptionId'])));
+  
+  // Save the new credit reference to the db.
+  $order->data = uc_credit_log_reference($order->order_id, $data['subscriptionId'], $order->payment_details['cc_number']);
+
+  return TRUE;
+}
+
+/**
+ * Cancel the recurring fee using the ARB api.
+ *
+ * @param $order
+ *   The order object.
+ * @param $fee
+ *   The fee object.
+ * @return
+ *   TRUE if recurring fee was cancelled
+ */
+function uc_recurring_authorizenet_arb_cancel($order, &$fee) {
+  $server = variable_get('uc_authnet_arb_mode', 'disabled');
+  
+  $order = uc_order_load($order->order_id);
+  $subscription_id = end(array_keys($order->data['cc_txns']['references']));
+
+  // Build the data array for the request.
+  $data = array(
+    'refId' => substr($order->order_id .'-'. time(), 0, 20),
+    'subscriptionId' => $subscription_id,
+  );
+
+  // Build the XML string.
+  $xml = _uc_authorizenet_xml_api_wrapper('ARBCancelSubscriptionRequest', _uc_authorizenet_array_to_xml($data));
+
+  // Send the request off to the server and get the response.
+  $response = uc_authorizenet_xml_api($server, $xml);
+
+  // Fail if the response is empty or FALSE.
+  if (!$response) {
+    return FALSE;
+  }
+
+  // Parse the response into a data array.
+  $data = _uc_authorizenet_arb_parse_response($response);
+
+  if ($data['resultCode'] == 'Error') {
+    if (!empty($order_id)) {
+      uc_order_comment_save($order_id, 0, t('Authorize.Net: Subscription @subscription_id cancellation failed.<br />@error - @text', array('@subscription_id' => $subscription_id, '@error' => $data['code'], '@text' => $data['text'])), 'admin');
+    }
+    return FALSE;
+  }
+
+  uc_order_comment_save($order_id, 0, t('Authorize.Net: Subscription @subscription_id cancelled.', array('@subscription_id' => $subscription_id)), 'admin');
+
+  // Let other modules act on the canceled fee.
+  if (!empty($fee)) {
+    module_invoke_all('uc_arb_cancel', $fee);
+  }
+
+  return TRUE;
+}
 
+/**
+ * Process a renewal using ARB
+ *
+ * Since authorize.net ARB handles recurring payments remotely,
+ * renewals always succeed.
+ *
+ * @param $order
+ *   The order object.
+ * @param $fee
+ *   The fee object.
+ * @return
+ *   TRUE if renewal succeeded
+ */
+function uc_recurring_authorizenet_arb_renew($order, &$fee) {
+  uc_payment_enter($order->order_id, $order->payment_method, $order->order_total, $fee->uid, array(), t('<b>ARB recurring fee</b>: @price', array('@price' => $order->order_total)));
   return TRUE;
 }
 
+/**
+ * Create form for updating credit card details for recurring fee.
+ */
+function uc_recurring_authorizenet_arb_update_form($form_state, $rfid) {
+  $form['rfid'] = array(
+    '#type' => 'value',
+    '#value' => $rfid,
+  );
+  $form['cc_data'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Credit card details'),
+    '#theme' => 'uc_payment_method_credit_form',
+    '#tree' => TRUE,
+  );
+  $form['cc_data'] += uc_payment_method_credit_form(array(), $order);
+  unset($form['cc_data']['cc_policy']);
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Update'),
+    '#suffix' => l(t('Cancel'), 'user/'. $user->uid),
+  );
+
+  return $form;
+}
+
+/**
+ * Implements update form submit for the authorizenet CIM gateway.
+ */
+function uc_recurring_authorizenet_arb_update_form_submit(&$form, &$form_state) {
+  $fee = uc_recurring_fee_user_load($form_state['values']['rfid']);
+  $order = uc_order_load($fee->order_id);
+  $order->payment_details = $form_state['values']['cc_data'];
+  $subscription_id = end(array_keys($order->data['cc_txns']['references']));
+    
+  if ($order->payment_details['cc_exp_month'] < 10) {
+    $order->payment_details['cc_exp_month'] = '0'. $order->payment_details['cc_exp_month'];
+  }
+
+  // Build the data array for the request.
+  $updates = array(
+    'payment' => array(
+      'creditCard' => array(
+        'cardNumber' => $order->payment_details['cc_number'],
+        'expirationDate' => $order->payment_details['cc_exp_year'] .'-'. $order->payment_details['cc_exp_month'],
+      ),
+    ),
+  );
+  
+  if (uc_authorizenet_arb_update($subscription_id, $updates, $order->order_id)) {
+    drupal_set_message('Account updated.');
+    $form_state['redirect'] = 'user/'. $form_state['values']['uid'];
+  }
+  else {
+    drupal_set_message('Account update failed.', 'error');
+  }
+}
