eWay recurring payment support

drasgardian - May 11, 2009 - 03:12
Project:Ubercart eWay Payment Gateway
Version:6.x-2.x-dev
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:needs review
Description

I would like to use use this module in conjunction with the eWay gateway.

There already exists a gateway module for eWay here: http://drupal.org/project/uc_eway

Details of eway's api for recurring payments is here: http://www.eway.com.au/Developer/LinkingtoeWAY/PaymentsRebill.aspx

I don't mind putting some development time towards this myself, but it would be great if someone who has worked on making gateway modules compatible with uc_recurring could talk me though what needs to be done before I dive into it.

Drasgard

#1

univate - May 11, 2009 - 05:02

How exaclty does eway handling renewals (from quickly skimming the docs it appears you need to query to see if the renewal has been processed)

You need to implement the following functions in the eway module (the last one is optional):

<?php
/**
* Implements callback uc_recurring_[payment_method]_fee()
*/
function uc_recurring_eway_fee($order, &$fee) {
 
// do your stuff here, ie: talk to gateway and setup rebilling
 
  // set the following variables
 
$fee->fee_handler = 'eway';
 
$fee->data = array(/* add your variables you need to track for the gateway here*/);  
 
  return
TRUE; // or FALSE if this setup rebilling process failed
}

/**
* Implements callback uc_recurring_[fee_handler]_renew()
*/
function uc_recurring_eway_renew($order, $fee) {
 
// do your stuff here, ie: talk to gateway and process the renewal, or in the case of eway
  // I think you just need to query to see if the gateway has processed the next payment
  //
  // NOTE: WORK STILL NEEDS TO BE DONE IN UC_RECURRING TO HANDLE FAILED
  //            PAYMENTS IN A NICE WAY

 
return TRUE; // or FALSE if the payment failed
}


/**
* Implements (*optional*) callback uc_recurring_[fee_handler]_fee_ops()
*/
function uc_recurring_eway_fee_ops($context, $fee) {
 
$ops = array();
  switch (
$context) {
     case
'fee_admin':
      
// add links to operations that admin users should be able to perform on a fee
       //  e.g. if the gateway supports changing the fee you could define this:
       // $ops[] = l('text', 'admin/store/order/recurring/'. $fee['rfid'] .'/edit';
      
break;
     case
'user':
      
// add links to operations that end users should be able to perform on their own fee
      
break;
  }
  return
$ops;
}
?>

#2

drasgardian - May 11, 2009 - 07:52
Assigned to:Anonymous» drasgardian

That's fantastic, thanks univate for your prompt reply - it's exactly the point in the right direction I needed. Hopefully I'll be able to take it from here and will post back soon with a uc_eway patch.

#3

ac - June 12, 2009 - 16:05

subscribing

#4

Justin W Freeman - June 12, 2009 - 21:26
Project:UC Recurring Fees» Ubercart eWay Payment Gateway
Version:6.x-2.x-dev» 6.x-1.0-beta1

Moving this to the uc_eway project. We need this feature too so will do it RSN.

#5

drasgardian - June 14, 2009 - 01:34
Assigned to:drasgardian» Anonymous

I have unassigned myself from this for now. Unfortunately haven't had a chance to get to it yet and it looks like someone else might get a chance before me.

#6

benkant - July 14, 2009 - 08:10
Version:6.x-1.0-beta1» 6.x-2.x-dev
Status:active» needs review

This zip file contains a patch for uc_eway to provide support for uc_recurring.

The NuSOAP library is required for SOAP calls to eWAY ReBill.

To install:

- patch uc_recurring (DRUPAL-6--2) with the patch I posted here #507936: Update for uc_recurring 2.x
- patch uc_eway (DRUPAL-6--2-2) with uc_eway_recurring.patch in this zip file
- copy uc_eway.recurring.inc from the zip file to the uc_eway module
- install the NuSOAP library to the uc_eway module directory as per the patched README.txt

No doubt this could be improved. I welcome comments and code.

AttachmentSize
uc_eway_recurring.zip 5.31 KB

#7

ac - July 14, 2009 - 08:55

Benkant's patches work here. Please test and review.

#8

thtas - July 14, 2009 - 17:00

great work benknat. testing :)

#9

thtas - July 15, 2009 - 16:29

okay its looking really good, but i've found a couple of small issues.

1. when anonymous checkout is enabled, the user_save call in _uc_eway_recurring_create_rebill_customer is made on the anon account (uid 0), and a user is not created. the user creation step is usually handled by the uc_cart module in uc_cart_complete_sale and when this comes around the user does get created, but we have no rebill_customer_id in the data fields, so all the subsequent gateway requests fail.

to fix this, i updated the $order object to to include our eway_rebill_customer_id in the data and added some code to the uc_cart_complete_sale function so that this bit of data is saved with a new account.

The problem is that changing the uc_cart module to include eway_rebill_customer_id doesn't make a lot of sense (adding eway code to the general cart module... not so cool), but there was no code in the complete_sale funtion to include any sort of custom data from the order. Can you think of any other way to do this? I was thinking maybe make a more complete user create within our _uc_eway_recurring_create_rebill_customer code, but then that seems like doubling up on existing functionality.

So any thoughts?

remaining issues are only small :)

2. in _uc_eway_recurring_create_rebill_customer, i cast all the variables in the request to string so that when they're empty it will still succeed. This was because i only wanted to pass the minimum required fields to eway (firstname,lastname,email) and it would break with empty object refs i think. empty strings are fine apparently.

e.g.

<?php
$data
= array(
   
'ewayCustomerID' => variable_get('uc_eway_customer_id', UC_EWAY_CUSTOMER_ID_DEFAULT),
   
'customerTitle' => '',
   
'customerFirstName' => (string)$order->billing_first_name,
   
'customerLastName' => (string)$order->billing_last_name,
   
'customerAddress' => (string)$order->billing_street1 . ' ' . $order->billing_street2,
   
'customerSuburb' => (string)$order->billing_city,
   
'customerState' => (string)uc_get_zone_code($order->billing_zone),
   
'customerCompany' => (string)$order->billing_company,
   
'customerPostCode' => (string) $order->billing_postal_code,
   
'customerCountry' => (string)$country[0]['country_name'],
   
'customerEmail' => (string)$order->primary_email,
   
'customerFax' => '',
   
'customerPhone1' => '',
   
'customerPhone2' => '',
   
'customerRef' => $order->uid,
   
'customerJobDesc' => '',
   
'customerComments' => '',
   
'customerURL' => '',
  );
?>

3. added some lines to the install file to remove some variables on un-install. i think the password is probably important to clean out.

<?php
  variable_del
('uc_eway_email_address');
 
variable_del('uc_eway_password');
 
variable_del('uc_eway_recurring_enabled');
 
variable_del('uc_eway_recurring_nusoap_path');
?>

I'll keep testing and fixing.

P.S.

Whats the best way to create a patch for the changes i make to your patch? or should i just continue to post things like i'm doing and you can roll them in to your code?

#10

Justin W Freeman - July 15, 2009 - 20:11
Status:needs review» needs work

@thtas Good work.

"Whats the best way to create a patch for the changes i make to your patch? or should i just continue to post things like i'm doing and you can roll them in to your code?"

@thtas standard practice is to provide a new patch against the current dev. version which incorporates benkant original patch. That way, anyone can pickup the last patch and apply it without having to read all the threads.

#11

thtas - July 17, 2009 - 01:26

okay i figured out how to get the rebill ID of a new customer associated with a new drupal user *after* the uc_cart_complete_sale function is called,

however it involves using hook_order. To me this still looks far from ideal, but least it's a solution which only involves a change to the eway module.

any thoughts on this? (added to uc_eway.recurring.inc)

it would be nice if there was a hook for cart_complete, but i can't seem to find one.

<?php
/*
implementation of ubercart hook_order
*/
function uc_eway_order($op, &$arg1, $arg2) {
   
$order = $arg1;
   
    switch(
$op)
    {
        case
'update':
                   
        if(
$order->order_status == 'pending' && isset($order->data['eway_rebill_customer_id']) && $order->uid != 0)
        {
           
drupal_set_message("DEBUG: updating user ". $order->uid. " to have the eway rebill id of ". $order->data['eway_rebill_customer_id']);
           
           
$account = user_load(array('uid' => $order->uid));
           
$account = user_save($account, array('eway_rebill_customer_id' => $order->data['eway_rebill_customer_id'] ));
        }
       
        break;
    }
}
?>

I'll put together a patch soon

#12

Justin W Freeman - July 21, 2009 - 06:09
Status:needs work» needs review

Here is a new patch which is the patch & new file from #6 with the changes from #9 and #11 added.
I also made a small change to the UC_EWAY_RECURRING_VAST_END_DATE constant in the uc_eway.recurring.inc file so that it is dynamicly created to +5 years instead of hard coded to 31/12/2015.

I will have a test of it now.

AttachmentSize
uc_eway_recurring_2.patch 19.01 KB

#13

ac - July 22, 2009 - 12:10

testing #12

#14

Justin W Freeman - August 4, 2009 - 23:54
Status:needs review» needs work

From my testing this doesn't work yet.

The hook uc_recurring_eway_fee never gets called because eway is a gateway of the credit payment method.

So when the payment is processed uc_recurring calls uc_recurring_credit_fee instead of uc_recurring_eway_fee.

I'll have to have a think and work out the best way to tackle this issue.

#15

univate - August 9, 2009 - 14:35

As outlined on the frontpage of the uc_recurring project any credit card gateways depends on the patch provided here #483494: changes to ubercart to work with uc_recurring

Although some ideas are being explored at the moment to remove that dependency and bring everything into uc_recurring.

#16

ac - September 3, 2009 - 10:20

The issue mentioned in #15 is no longer required if you are using HEAD. This may require the patch in #12 to be rerolled.

#17

univate - September 3, 2009 - 13:37

With some recent changes to uc_recurring 2.x payment gateways require an extra function to declare their callback functions:

So instead of having the 'magic' function names like uc_recurring_[fee_handler]_renew() you will need a functions that declares the callbacks like below:

<?php
/**
*
*/
function uc_eway_recurring_info() {
 
$items['eway'] = array(
   
'title' => t('Eway Payment Gateway'),
   
'module' => 'uc_eway',
   
'payment method' => 'credit',
   
'process' => 'uc_recurring_eway_fee',
   
'renew' => 'uc_recurring_eway_renew',
  );
  return
$items;
}
?>

You may also need to check the arguments that the 'process' and 'renew' functions take as they need to take $order and $fee objects. I think there where some inconsistencies previous where sometimes the $fee argument was an array and other times it was an object.

e.g,

#18

thtas - September 28, 2009 - 22:14

looks like the info function needs to declare functions for "process callback" and "renew callback", not sure when that change happened.

<?php
function uc_eway_recurring_info() {
 
$items['eway'] = array(
   
'title' => t('Eway Payment Gateway'),
   
'module' => 'uc_eway',
   
'payment method' => 'credit',
   
'process callback' => 'uc_recurring_eway_fee',
   
'renew callback' => 'uc_recurring_eway_renew',
  );
  return
$items;
}
?>

#19

Justin W Freeman - October 2, 2009 - 06:21
Title:eWay support» eWay recurring payment support

Marked #507936: Update for uc_recurring 2.x as a duplicate of this issue so it's easier to keep track of.

Changing title.

#20

Justin W Freeman - October 2, 2009 - 06:31

Here is the work from http://drupal.org/node/507936#comment-2063014 with the code from #18 in it.

The file includes all the changes and will apply to 6.x-2.x-dev

I have tested this with:
ubercart 6.x-2.x-rc7
uc_recurring 6.x-2.0-alpha1
uc_eway 6.x-2.x-dev

It seems to be almost working. Everything went through alright and the recurring payment was created in eway but when I go into the eway pending transactions screen I see
Customer Name Transaction Number Value of Transactions
Reuben Turk 2280 $2280.00

- There are supposed to be 2 recurring payments at $1.10 each. I'm guessing it is taking the transaction number as the value of transactions.
Can anyone confirm or explain this?

AttachmentSize
uc_eway_recurring_3.patch 18.14 KB

#21

Justin W Freeman - October 2, 2009 - 06:31
Status:needs work» needs review

#22

Justin W Freeman - October 5, 2009 - 23:26
Status:needs review» needs work

On closer inspection, it seems that the problem with the pending transactions table is the UC_EWAY_RECURRING_VAST_END_DATE date.

My recurring payment should have been one recurring payment each day for two days but instead is doing one recurring payment each day for 2280 days (that was how many days until December 31st 2015 = UC_EWAY_RECURRING_VAST_END_DATE).

Will have a look into this soon when I get a few moments of spare time.

#23

benkant - October 8, 2009 - 23:49

One possible fix would be to add a new rebill event each time one is successfully processed, and doing that indefinitely if there is no end date... instead of creating rebill events up until UC_EWAY_RECURRING_VAST_END_DATE at the outset.

#24

Justin W Freeman - October 12, 2009 - 05:03

The bug for the end date was that _uc_eway_recurring_create_rebill_event was using $fee->number_intervals instead of $fee->remaining_intervals
If you fix that, it creates a rebill event with the correct number of rebills.

There are a couple of other things I've noticed that need work before I roll a new patch too.

In _uc_eway_recurring_create_rebill_event there is a part that is:

  $initial_charge = split(' ', $fee->initial_charge);
  if ((int)$initial_charge[0] === 0) {
    $init_fee = (int)$fee->fee_amount * 100;
  }
  else {
    $init_fee = 0;
  }

$fee->initial_charge doesn't seem to exist, or does it only exist sometimes?

Also, on the recurring fees orders page (admin/store/orders/recurring) I get:
ID Order Amount Next Interval Left Total Operations
1 9 $1.00 10/03/2009 - 15:43 1 days 2 2
3 481 $1.00 10/13/2009 - 14:34 1 days 2 2

There used to be an option to charge a rebill by clicking a link.
This is now supposed to be provided in the menu part of uc_eway_recurring_info.
Is this option purposely left out of this patch because eway takes care of the rebilling?

My recurring fees on this table also say there are 2 rebills left. When eway rebills these the 'Left' number never changes. Is there anyway for drupal to know that these rebill have been actioned?

I also noticed I am having orders added to the uc_orders table every 15 minutes. I would guess they have something to do with cron.
They are all pending orders.
My recurring product is called Test recurring payments
These 15 minute order are for a product called Renewal of product Test recurring payments

Do you know if this should be happening and why?

#25

univate - October 12, 2009 - 08:43

Couple of comments about the patch above in #20:

+++ uc_eway.recurring.inc 2009-10-02 10:02:01.000000000 +1000
@@ -0,0 +1,410 @@
+    'process callback' => 'uc_recurring_eway_fee',
+    'renew callback' => 'uc_recurring_eway_renew',
+  );
+  return $items;
+}
+
+/**
+ * Implements callback uc_recurring_[payment_method]_fee()
+ */
+function uc_recurring_eway_fee($order, &$fee) {

I would rename these functions to uc_eway_recurring_process() and uc_eway_recurring_renew() - there is no reason to use the uc_recurring namespace for external modules.

+++ uc_eway.recurring.inc 2009-10-02 10:02:01.000000000 +1000
@@ -0,0 +1,410 @@
+/**
+ * Implements (*optional*) callback uc_recurring_[fee_handler]_fee_ops()
+ */
+function uc_recurring_eway_fee_ops($context, $fee) {
+  $ops = array();
+  switch ($context) {
+     case 'fee_admin':
+       $ops[] = l('delete', 'admin/store/orders/recurring/'. $fee['rfid'] .'/delete');
+       break;
+     case 'user':
+       // add links to operations that end users should be able to perform on their own fee
+       break;
+  }
+  return $ops;
+}

You can delete this function, instead user operations are being defined as menu items in the hook_recurring_info (its just cleaner with this all in the one place)

Also I'm presuming by delete you really are taking about a cancel operation.

<?php
+/**
+ * Implementation of hook_recurring_info().
+ */
+function uc_eway_recurring_info() {
$items['eway'] = array(
+   
'title' => t('Eway Payment Gateway'),
+   
'module' => 'uc_eway',
+   
'payment method' => 'credit',
+   
'process callback' => 'uc_recurring_eway_fee',
+   
'renew callback' => 'uc_recurring_eway_renew',
+   
'cancel callback' => '_uc_eway_recurring_delete_rebill_event',
+   
'menu' => array(
+     
'cancel' => UC_RECURRING_MENU_DEFAULT,
+    ),
+  );
+  return
$items;
+}
?>

But for the above cancel function to work you will also need to change the arguments of the function _uc_eway_recurring_delete_rebill_event to just accept the recurring $fee object and then get the user details in that function.

Also the default functionality of cancel in uc_recurring is to give that option to both user and admins.

+++ uc_eway.recurring.inc 2009-10-02 10:02:01.000000000 +1000
@@ -0,0 +1,410 @@
+/**
+ * Implements hook_recurring_api().
+ */
+function uc_eway_recurring_api($op, $id) {
+  switch ($op) {
+    case 'delete':
+      $fee = db_fetch_array(db_query("SELECT * FROM {uc_recurring_users} WHERE rfid = %d", $id));
+      $fee['data'] = unserialize($fee['data']);
+      $account = user_load(array('uid' => $fee['uid']));
+      _uc_eway_recurring_delete_rebill_event($fee, $account);
+      break;
+  }
+}

There is still some discussion around the other hooks. The current opinion is that these should be all separate like the direction D7 is taking.

So the the recurring fee delete hook is now currently defined as:

<?php
hook_recurring_user_delete
($rfid)
?>

Also there is an API function for getting the recurring fee from an ID (so you don't have to actually call unserialize as well):

<?php
$fee
= uc_recurring_fee_user_load($rfid);
?>

This review is powered by Dreditor.

#26

Justin W Freeman - October 16, 2009 - 01:08

Thanks for the input Chris.

This patch has the changes mentioned in #25 (because of this it now needs to be used with uc_recurring 6.x-2.x-dev as it uses hooks not in 6.x-2.0-alpha1)
as well as changes to $fee->number_intervals and $fee->initial_charge parts as mentioned in #24.

At the moment the only issues i'm seeing are the many pending order that are being created every cron run and the fact that the number of rebills doesn't get updated on the drupal order after eway does a rebill. These issues may well be linked.

So as soon as I sort that out we should have a working candidate.

AttachmentSize
uc_eway_recurring_4.patch 17.5 KB

#27

Justin W Freeman - October 16, 2009 - 05:18

Oops, the changes from #9 & #11 got missed in #20

In this patch they are back in.
I have also changed the watchdog functions to to use variables.

AttachmentSize
uc_eway_recurring_5.patch 19.59 KB

#28

univate - October 16, 2009 - 11:54

+++ uc_eway.recurring.inc 2009-10-16 16:13:45.000000000 +1100
@@ -0,0 +1,387 @@
+    $fee->fee_handler = 'eway';
+    $fee->data = array('rebill_id' => $result['RebillID']);

There is no need to set the fee_handler anymore, uc_recurring sets all this up based on the settings in the hook_recurring_info function.

Also the data element is a place we any module can store things so its best to just add the variables you want to store there rather then override everything.

So I would replace the above two lines with the following:

<?php
$fee
->data['rebill_id'] = $result['RebillID'];
?>

This review is powered by Dreditor.

#29

Justin W Freeman - October 20, 2009 - 00:50
Status:needs work» needs review

Thanks again for the help univate.

Here is a version that from my testing seems to work :)

New for this one:
* Bug fix for a bug introduced in #27
* Added univate's change from #28
* Fixed a couple of places where $fee was being used as an array instead of an object (this is what was causing uc_recurring_eway_renew to always return FALSE)

Anyone else who can test this please do.

I will roll this patch into 6.x-2.x-dev shortly, which will make for easier testing, but I will probably not make a release until ubercart & uc_recurring both have their 2.0 releases.

AttachmentSize
uc_eway_recurring_6.patch 19.54 KB

#30

Justin W Freeman - October 21, 2009 - 01:17

Here is a new version. Fixes for this version are:
* Fixed results checking of the response from eway when a recurring payment is cancelled - eway documentation for what gets returned is wrong :(
* Fixed number of rebills on eway end. The end date was not being calculated correctly so one rebill would be missed.

I am going to commit this version of the patch to 6.x-2.x-dev

AttachmentSize
uc_eway_recurring_7.patch 19.78 KB

#31

Justin W Freeman - October 21, 2009 - 01:56
Status:needs review» fixed

Patch in #30 committed to 6.x-2.x-dev

A proper release will probably not be done until ubercart & uc_recurring both have their 2.0 releases.

So until then please test test test and if you find any problems in there please open a new issues.

#32

univate - October 21, 2009 - 02:15

You are missing the 'fee handler' item in uc_eway_recurring_info() , this function should be:

<?php
+/**
+ * Implementation of hook_recurring_info().
+ */
+function uc_eway_recurring_info() {
$items['eway'] = array(
+   
'title' => t('Eway Payment Gateway'),
+   
'module' => 'uc_eway',
+   
'payment method' => 'credit',
+   
'fee handler' => 'eway',
+   
'process callback' => 'uc_eway_recurring_process',
+   
'renew callback' => 'uc_recurring_eway_renew',
+   
'cancel callback' => '_uc_eway_recurring_delete_rebill_event',
+   
'menu' => array(
+     
'cancel' => UC_RECURRING_MENU_DEFAULT,
+    ),
+  );
+  return
$items;
+}
?>

This review is powered by Dreditor.

#33

Justin W Freeman - October 21, 2009 - 03:31

Thanks.

I have committed the change in #32

#34

benkant - October 22, 2009 - 04:50
Status:fixed» needs review

Hi Justin/Chris,

The code in CVS at the moment doesn't work for me. Creating a rebill event at checkout fails for anonymous users, as in uc_eway_recurring_process() the order does not have a user yet. To fix this I save the created RebillID to the fee object rather than the account, and then implement hook_uc_checkout_complete() to save that RebillID to the user object once checkout is complete and the new user has been created.

Regarding #24 and having pending orders added every cron run: this is because eWay does recurring billing a bit differently, in that it does it automatically. Therefore in the 'renew callback', we needn't actually do a renewal, we need only test that the rebill transaction was successful. But, we don't want to check for a successful transaction until it has be tried. For this reason I have used uc_recurring's:

$fee->own_handler = TRUE;

when initially populating the fee object. I then implemented hook_cron() to do our own renewal checks. In that cron function we grab a list of fees, and only call the renew function if the transaction is no longer pending. We are unable to do this by just implementing the 'renew callback' in uc_recurring, as the return values from that indicate either 'SUCCESS' or 'FAILURE' where eWay has a third state 'PENDING'.

So attached is a patch created from the current DRUPAL-6--2 branch. It contains far too much debug information to be used in production, so it will need to be cleaned up a bit before we make a release out of this branch.

Please review and let me know how it goes.

Cheers

AttachmentSize
uc_eway_recurring_anon.patch 15.82 KB

#35

univate - October 22, 2009 - 23:48

+++ uc_eway.recurring.inc 22 Oct 2009 03:41:32 -0000
@@ -95,10 +220,83 @@ function uc_recurring_eway_renew($order,
+function uc_eway_recurring_renew($fee) {

Do you really need to re-implement the renew function? Can't you just reuse the existing uc_recurring_renew() function. That way you avoid code duplication and also get the benefit of any improvements to the renewal process - I can already see you don't have the CA stuff in there that the current uc_recurring version has.

This is what I am doing for the Paypal and Auth.net ARB gateways, since they trigger the renewals they call the uc_recurring_renew function rather then the hook_cron() function in uc_recurring.

This review is powered by Dreditor.

#36

benkant - October 25, 2009 - 07:01

Here is the patch from #34, without the re-implementation of uc_recurring_renew(). Thanks for your comments univate.

I've tested it here and it appears to be working well. Again, there's lots of debug in here that needs be removed before commit, but I thought I'd leave it in to help with testing.

Please review!

Cheers

AttachmentSize
uc_eway_recurring_anon2.patch 15.62 KB

#37

Justin W Freeman - October 26, 2009 - 22:37

@benkant:

Thanks for the patch, I'll have a look at it ASAP.

Sorry, I should have mentioned earlier (in regards to the pending orders problem in #24) that there was not actually any problem with using uc_recurrings renew function.
The many pending orders were actually caused by a different bug in uc_eway.recurring.inc that has since been fixed.
I was also originally thinking to do our own recurring_renew function until I solved that other bug.
The thing I had on my todo list that I forgot was to make sure the status got updated from pending properly at the end.

#38

thtas - October 29, 2009 - 00:38

Testing the patch from #36
So far so good with Ubercart 2.0, eway 6.x-2.x-dev (2009-10-21) and uc_recurring 2.0 alpha 2.

Great work :)

#39

thtas - October 29, 2009 - 22:56

Okay I think there might be something wrong with how this is working, but i need some insight in to how it all fits together to properly diagnose the issue... I'll try my best to describe everything.

I decided to try a small test transaction on the live gateway, but we hadn't enabled the rebill service with eway yet so all our rebill requests failed (fair enough!).
A message is displayed "problem with recurring payment.." and the user is taken back to the checkout.

However, they still get charged for a single amount and it shows up in eway, emails are sent to the user by ubercart etc.
This means that if a customer tries to attempt the checkout process again they will get charged *again*... not good right?

So i switched it all back to test mode and added some debug statements to see what's going on.
I also made any uc_recurring requests fail (returning false) to try and replicate this problem in test.

So here is what's happening as far as i can tell:

1. uc_eway_charge is called with the amount that the user wants to make as a recurring payment (why does this happen before any recurring stuff??)
2. _uc_eway_recurring_create_rebill_customer is then called and fails returning the anonymous user, but at this point i think everything is seen to still be okay by our modules..
3. _uc_eway_recurring_create_rebill_event is then called, but we have 'RebillCustomerID' => stdClass::__set_state(array( 'uid' => '0')) in our params so it fails.
4. Error messages are set, user is bounced back to checkout... but #1 has still done it's thing.

There are a couple of issues i can see here

A. The order of operations seems to be a bit messed up to me. If we're creating a rebill event, do we need to do a normal charge call as well? And If we do, shouldn't this come *after* the call to create the rebill event?
B. When the call to create a rebill customer fails, an error should be returned instead of the current user object. I was going to work on fixing this one myself and posting a patch.

Anybody have any ideas about 'A' though?

Cheers,

-Tim

#40

thtas - October 29, 2009 - 23:31

This is just a patch for my issue 'B' above

AttachmentSize
uc_eway_recurring_anon3.patch 15.72 KB

#41

thtas - October 29, 2009 - 23:34

This is just a patch for my issue 'B' above

just made the call to create a rebill customer return false if it fails

<?php
/**
* Create Rebill Customer
*/
function _uc_eway_recurring_create_rebill_customer($order) {
 
//$account = user_load(array('uid' => $order->uid));

 
$country = uc_get_country_data(array('country_id' => $order->billing_country));

 
$data = array(
   
'ewayCustomerID' => variable_get('uc_eway_customer_id', UC_EWAY_CUSTOMER_ID_DEFAULT),
   
'customerTitle' => '',
   
'customerFirstName' => (string) $order->billing_first_name,
   
'customerLastName' => (string) $order->billing_last_name,
   
'customerAddress' => (string) $order->billing_street1 . ' ' . $order->billing_street2,
   
'customerSuburb' => (string) $order->billing_city,
   
'customerState' => (string) uc_get_zone_code($order->billing_zone),
   
'customerCompany' => (string) $order->billing_company,
   
'customerPostCode' => (string) $order->billing_postal_code,
   
'customerCountry' => (string) $country[0]['country_name'],
   
'customerEmail' => (string) $order->primary_email,
   
'customerFax' => '',
   
'customerPhone1' => '',
   
'customerPhone2' => '',
   
'customerRef' => $order->uid,
   
'customerJobDesc' => '',
   
'customerComments' => '',
   
'customerURL' => '',
  );

 
$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'],
    ));
    */
 
}
  else
  {
      return
FALSE;
  }

 
//return $account;
}
?>

AttachmentSize
uc_eway_recurring_anon3.patch 15.72 KB

#42

univate - October 30, 2009 - 05:27

There is another way to look at that issue:
* you don't want to setup a recurring fee schedule unless you know you can actually charge them.
* if the charge occurs and the payment gateway is fully tested and working the likelihood of the recurring fee setup failing is very low.

The worst case if the system can't setup the recurring fee is that you just have to get them to renew manually when its due.

#43

thtas - October 30, 2009 - 17:51

Hm true.
I forgot there were the settings in the uc_recurring module which allow us to determine what happens to the checkout process if recurring fees fail during checkout.
I'd be happy if the recurring fee failed the user was told that their initial payment was successful, but the scheduling failed and to contact support or whatever.

However, i'm not sure if that particular feature of uc_recurring is working?

i.e. under the recurring feature settings, if I set the "Action to take if a recurring fee fails to process during checkout" to "Return a failed message but complete checkout." it seems to just return the user to the checkout page instead of checkout/complete regardless of what settings are used in the feature.

This is probably an issue for the uc_recurring or even the uc_order module issue list though...

#44

Justin Freeman - November 5, 2009 - 04:03

Quick question. How are credit card expiry dates handled with uc_recurring / uc_eway ? Would be great to notify the customer and store owner that a credit card is due to expire in X weeks, rather than just let the card expire and have recurring cease. Customers expect this level of service now from on-line subscriptions.

Has any thought gone into this case?

#45

univate - November 11, 2009 - 03:11

@thtas, I'm not aware of any problems although I haven't testing that recently - post a bug to the uc_recurring issue queue if you are certain there is a problem.

@Justin Freeman, I have added a feature request to uc_recurring about managing credit card expiry better - I agree this is necessary feature - #629352: Credit card expiry reminder

 
 

Drupal is a registered trademark of Dries Buytaert.