Closed (duplicate)
Project:
Ubercart eWay Payment Gateway
Version:
6.x-2.x-dev
Component:
Code
Priority:
Normal
Category:
Feature request
Assigned:
Reporter:
Created:
11 May 2009 at 03:12 UTC
Updated:
30 Apr 2010 at 06:02 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
univate commentedHow 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):
Comment #2
drasgardian commentedThat'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.
Comment #3
acsubscribing
Comment #4
agileware commentedMoving this to the uc_eway project. We need this feature too so will do it RSN.
Comment #5
drasgardian commentedI 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.
Comment #6
benkant commentedThis 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.
Comment #7
acBenkant's patches work here. Please test and review.
Comment #8
thtas commentedgreat work benknat. testing :)
Comment #9
thtas commentedokay 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.
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.
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?
Comment #10
agileware commented@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.
Comment #11
thtas commentedokay 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.
I'll put together a patch soon
Comment #12
agileware commentedHere 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.
Comment #13
actesting #12
Comment #14
agileware commentedFrom 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.
Comment #15
univate commentedAs 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.
Comment #16
acThe issue mentioned in #15 is no longer required if you are using HEAD. This may require the patch in #12 to be rerolled.
Comment #17
univate commentedWith 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:
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,
Comment #18
thtas commentedlooks like the info function needs to declare functions for "process callback" and "renew callback", not sure when that change happened.
Comment #19
agileware commentedMarked #507936: Update for uc_recurring 2.x as a duplicate of this issue so it's easier to keep track of.
Changing title.
Comment #20
agileware commentedHere 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?
Comment #21
agileware commentedComment #22
agileware commentedOn 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.
Comment #23
benkant commentedOne 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.
Comment #24
agileware commentedThe 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:
$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?
Comment #25
univate commentedCouple of comments about the patch above in #20:
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.
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.
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.
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:
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):
This review is powered by Dreditor.
Comment #26
agileware commentedThanks 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.
Comment #27
agileware commentedOops, 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.
Comment #28
univate commentedThere 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:
This review is powered by Dreditor.
Comment #29
agileware commentedThanks 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.
Comment #30
agileware commentedHere 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
Comment #31
agileware commentedPatch 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.
Comment #32
univate commentedYou are missing the 'fee handler' item in uc_eway_recurring_info() , this function should be:
This review is powered by Dreditor.
Comment #33
agileware commentedThanks.
I have committed the change in #32
Comment #34
benkant commentedHi 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:
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
Comment #35
univate commentedDo 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.
Comment #36
benkant commentedHere 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
Comment #37
agileware commented@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.
Comment #38
thtas commentedTesting 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 :)
Comment #39
thtas commentedOkay 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
Comment #40
thtas commentedThis is just a patch for my issue 'B' above
Comment #41
thtas commentedThis is just a patch for my issue 'B' above
just made the call to create a rebill customer return false if it fails
Comment #42
univate commentedThere 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.
Comment #43
thtas commentedHm 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...
Comment #44
Justin Freeman commentedQuick 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?
Comment #45
univate commented@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
Comment #46
Anonymous (not verified) commentedI had some problems with uc_eway 6.x-2.x-dev in relation to recurring payments.
I found that the recurring payment functionality (uc_eway.recurring.inc) was stripping off the decimals from my RebillRecurAmt, so that an amount $19.95 would be submitted as $19.00, in the following line:
'RebillRecurAmt' => (int) $fee->fee_amount * 100,
I removed the (int) and it works fine now. My understanding is that (int) converts a string to an integer but it seems to work fine without it.
I also found that the "RebillEndDate" was before the "RebillStartDate. I'm not sure what was causing this, so I just hard-coded a date way in the future by replacing this:
'RebillEndDate' => $end_date,
with this:
'RebillEndDate' => '31/12/2020',
After I fixed this, I also had a problem with the RebillStartDate being yesterday, must have to do with my setup's default time zone, so I added the following line as well:
date_default_timezone_set("Australia/Sydney");
Working nicely now.
Comment #47
benkant commentedI've collated all the issues here and created a patch that should fix issues. I've created a new issue #785990: Please test recurring patch for testing. Please test and give feedback.