diff --git payment/uc_credit/test_gateway.module payment/uc_credit/test_gateway.module
index 1d6e2b7..14e3a65 100644
--- payment/uc_credit/test_gateway.module
+++ payment/uc_credit/test_gateway.module
@@ -67,3 +67,97 @@ function test_gateway_charge($order_id, $amount, $data) {
 
   return $result;
 }
+
+/**
+ * Callback to process a recurring renewal
+ */
+function uc_recurring_test_gateway_renew($order, $fee) {
+  if ($key = uc_credit_encryption_key()) {
+    $crypt = new uc_encryption_class;
+    $fee['data']['payment_details']['cc_number'] = $crypt->decrypt($key, $fee['data']['payment_details']['cc_number']);
+    if (variable_get('uc_credit_debug', FALSE)) {
+      $fee['data']['payment_details']['cc_cvv'] = $crypt->decrypt($key, $fee['data']['payment_details']['cc_cvv']);
+    }
+    $fee['data']['payment_details']['cc_exp_month'] = $crypt->decrypt($key, $fee['data']['payment_details']['cc_exp_month']);
+    $fee['data']['payment_details']['cc_exp_year'] = $crypt->decrypt($key, $fee['data']['payment_details']['cc_exp_year']);
+    uc_store_encryption_errors($crypt, 'uc_recurring');
+  }
+
+  // Cache the CC details stored by the handler.
+  uc_credit_cache('save', $fee['data']['payment_details'], FALSE);
+
+  // Run the charge.
+  $result = test_gateway_charge($fee['order_id'], $fee['fee_amount'], NULL);
+
+  // Handle the result.
+  if ($result['success'] === TRUE) {
+    uc_payment_enter($fee['order_id'], 'credit', $fee['fee_amount'], 0, $result['data'], t('Recurring fee payment.') .'<br />'. $result['comment']);
+  }
+  else {
+  }
+
+  return $result['success'];
+}
+
+/**
+ * Callback function for setting up a recurring fee
+ */
+function uc_recurring_test_gateway_fee($order, &$fee) {
+  $data = array(
+    'billing_first_name' => $order->billing_first_name,
+    'billing_last_name' => $order->billing_last_name,
+    'billing_phone' => $order->billing_phone,
+    'billing_company' => $order->billing_company,
+    'billing_street1' => $order->billing_street1,
+    'billing_street2' => $order->billing_street2,
+    'billing_city' => $order->billing_city,
+    'billing_zone' => $order->billing_zone,
+    'billing_postal_code' => $order->billing_postal_code,
+    'billing_country' => $order->billing_country,
+    'payment_details' => $order->payment_details,
+    'model' => $fee->model,
+  );
+
+  if ($key = uc_credit_encryption_key()) {
+    $crypt = new uc_encryption_class;
+    $data['payment_details']['cc_number'] = $crypt->encrypt($key, $data['payment_details']['cc_number'], 32);
+    if (variable_get('uc_credit_debug', FALSE)) {
+      $data['payment_details']['cc_cvv'] = $crypt->encrypt($key, $data['payment_details']['cc_cvv'], 32);
+    }
+    $data['payment_details']['cc_exp_month'] = $crypt->encrypt($key, $data['payment_details']['cc_exp_month'], 32);
+    $data['payment_details']['cc_exp_year'] = $crypt->encrypt($key, $data['payment_details']['cc_exp_year'], 32);
+    uc_store_encryption_errors($crypt, 'uc_recurring');
+
+    // need to set gateway specific fee information for renewals
+    $fee->fee_handler = 'test_gateway';
+    $fee->data = $data;
+  }
+
+  return TRUE;
+}
+
+/**
+ * Callback for uc_recurring_fee_ops().
+ */
+function uc_recurring_test_gateway_fee_ops($context, $fee) {
+  $ops = array();
+
+  switch ($context) {
+    case 'fee_admin':
+      if ($fee['remaining_intervals'] > 0) {
+        $ops[] = l(t('edit'), 'admin/store/orders/recurring/'. $fee['rfid'] .'/edit');
+        $ops[] = l(t('cancel'), 'admin/store/orders/recurring/'. $fee['rfid'] .'/cancel');
+      }
+      else {
+        $ops[] = l(t('delete'), 'admin/store/orders/recurring/'. $fee['rfid'] .'/delete');
+      }
+      break;
+    case 'user':
+      $ops[] = l(t('Cancel'), 'user/'. $fee['uid'] .'/recurring/'. $fee['rfid'] .'/cancel');
+      break;
+  }
+
+  return $ops;
+}
+  
+
diff --git payment/uc_credit/uc_credit.module payment/uc_credit/uc_credit.module
index 0f09285..60e0a65 100644
--- payment/uc_credit/uc_credit.module
+++ payment/uc_credit/uc_credit.module
@@ -382,7 +382,6 @@ function uc_credit_payment_method() {
   return $methods;
 }
 
-
 /*******************************************************************************
  * Callback Functions, Forms, and Tables
  ******************************************************************************/
@@ -871,6 +870,19 @@ function uc_credit_settings_form_validate($form, &$form_state) {
   }
 }
 
+/**
+ * Callback function for setting up a recurring credit card fee
+ */
+function uc_recurring_credit_fee($order, &$fee) {
+  $handler = 'uc_recurring_'. uc_credit_default_gateway() .'_fee';
+  if (function_exists($handler)) {
+    return $handler($order, $fee);
+  }
+  // no available recurring fee handler for the default credit card gateway
+  return FALSE; 
+}
+
+
 // Creates the encryption key file if it doesn't already exist.
 function uc_credit_settings_form_submit($form, &$form_state) {
   if ($_SESSION['update_cc_encrypt_dir'] === TRUE) {
diff --git payment/uc_payment_pack/uc_payment_pack.module payment/uc_payment_pack/uc_payment_pack.module
index f97d3d4..67de964 100644
--- payment/uc_payment_pack/uc_payment_pack.module
+++ payment/uc_payment_pack/uc_payment_pack.module
@@ -370,3 +370,56 @@ function uc_payment_method_check($op, &$arg1) {
   }
 }
 
+/**
+ * Callback for setting up a manual recurring fee using check as payment method.
+ */
+function uc_recurring_check_fee($order, &$fee) {
+  $fee->fee_handler = 'manual';
+  return TRUE;
+}
+
+/**
+ * Callback for setting up a manual recurring fee using cod as payment method.
+ */
+function uc_recurring_cod_fee($order, &$fee) {
+  $fee->fee_handler = 'manual';
+  return TRUE;
+}
+
+/**
+ * Callback for setting up a manual recurring fee using other as payment method.
+ */
+function uc_recurring_other_fee($order, &$fee) {
+  $fee->fee_handler = 'manual';
+  return TRUE;
+}
+
+/**
+ * Callback for processing a renewal for recurring fee
+ */
+function uc_recurring_manual_renew($order, &$fee) {
+  return TRUE;
+}
+
+/**
+ * Callback for processing a renewal for recurring fee
+ */
+function uc_recurring_manual_fee_ops($context, $fee) {
+  $ops = array();
+  switch ($context) {
+    case 'fee_admin':
+      if ($fee['remaining_intervals'] > 0) {
+        $ops[] = l(t('edit'), 'admin/store/orders/recurring/'. $fee['rfid'] .'/edit');
+        $ops[] = l(t('cancel'), 'admin/store/orders/recurring/'. $fee['rfid'] .'/cancel');
+      }
+      else {
+        $ops[] = l(t('delete'), 'admin/store/orders/recurring/'. $fee['rfid'] .'/delete');
+      }
+      break;
+    case 'user':
+      $ops[] = l(t('Cancel'), 'user/'. $fee['uid'] .'/recurring/'. $fee['rfid'] .'/cancel');
+      break;
+  }
+
+  return $ops;
+}
