22 replies [Last post]
Ryan's picture
Offline
Joined: 08/07/2007
Juice: 15438
Was this information Helpful?

Alrighty, I've got in working order a recurring payments module, and I'm looking for folks to check it out, test it, and see if it makes sense. Smiling

First, I'll try to spell out what the module is not: this is not a one-stop killer module to handle anyone's recurring payment needs. Neither is it an interface to every payment gateway imaginable. It will also never become either of these things. So... what is it good for?

Well, the module is good for providing a framework for your modules to hook into. That's what we want in core, right? Eye-wink It does provide a product fee called "recurring fee" that you can attach to a product/SKU. With this you can specify a fee amount, an initial charge (relative to checkout), an interval for further charges, and the total number of intervals. When a customer goes to checkout, the module will restrict them to the payment method options on your site that work for recurring payments. (These can be adjusted in the product features settings form for recurring payments.) Once they complete checkout, the module passes the fee information onto the recurring payment handler of your choice for processing. The rest is up to your handler.

The module also provides a very basic default handler. This depends on you using some sort of credit card payment processor and stores CC data locally to be charged on the proper intervals. There's a cron task to do this automatically, and there's also an admin menu at /admin/store/orders/recurring that lets you tweak the fees and charge them manually. This also includes a few workflow events and a hook_recurring_api($op, $fee) for modules to hook into. I highly recommend using CC encryption if you intend to go this route. Eye-wink

The default handler can be an example in some ways for others to build on in their own modules. It's my understanding that a lot of payment gateways have built in subscription management. In that case, you'll need to code your own functions to setup subscriptions and decide what to do when someone's charge fails or their subscription expires. To be the most flexible, I highly recommend invoking the hook and workflow events you'll see invoked in the uc_recurring_charge() function at the bottom of the module.

Handlers are made by simply implementing hook_recurring_fee($order, $fee) in your module. The arguments are pretty self-explanatory. You can dump $fee with print_r() to see what it contains... basically all the info from the product feature.

I don't intend to work on this indefinitely, and I want it to stay slim. But I want some assessment as to the ease of use for the product feature and the default handler, and I also want to know if anything is lacking for folks to use this as a framework to build their own handlers.

This is the last major hurdle on my beta-do list, so thanks for any help! Cool

PreviewAttachmentSize
uc_recurring.tar40.5 KB
giorgio79@drupal.org's picture
Offline
Joined: 02/02/2008
Juice: 280
Dear Ryan, Thank you very

Dear Ryan,

Thank you very much!

I will be testing this for sure.

I am a bit dizzy by all the Recurring / Subscriptions modules, and I am posting links to those as well for reference. Maybe we can take the best from all of these, and combine them into a single kick ass recurring module (even though it was stated this one is not meant to be an all in all solution but a preprocessor for the payment gateways, and these latter should do their own thing regarding recurring stuff) Sticking out tongue

http://www.ubercart.org/contrib/2851#comment-12320
http://www.ubercart.org/contrib/1461

Zahor@drupal.org's picture
Offline
Joined: 10/30/2007
Juice: 84
recurring billing with authorize.net

Authorize.net recently added a new feature called the "Customer Information Manager" to store/manage customer data for recurring billing. For those who use them, this will save them having to store cc data on their own servers. The guide can be found here: http://www.authorize.net/support/CIM_XML_guide.pdf
They provide sample intergration code here: http://developer.authorize.net/samplecode
Hopefully that can help.

Hanno's picture
Offline
Joined: 02/28/2008
Juice: 12
Great

I will also be glad to test this module. We need a module to generate monthly bills to stay member in a certain role. The payment method we use is a batchmethod called automatic incasso to send to the bank on a monthly base.
We will go live in June and would like to test this in our situation.

Hanno's picture
Offline
Joined: 02/28/2008
Juice: 12
recurring payments versus recurring orders

I am not sure if we have it clear what situations we might have for recurring events.

1. The situation that someone buys a product but wants to pay for it in several stages.
What we need then is a partial payment for every period, and a single order and invoice.

2. The situation that we have a product that we want to renew every period, with a new order and invoice

3. The situation that we would like to have a order recurred, with a set of products included.

This module is focusing on the first situation, while subscriptions is focusing on the second situation am i right?

Ryan's picture
Offline
Joined: 08/07/2007
Juice: 15438
Re: recurring payments versus recurring orders

This module is more for the second situation where you attach a recurring fee to a product, like a monthly membership fee. It mostly facilitates this sort of work, though, and will most likely need to be integrated into your payment service.

chadcrew's picture
Offline
Bug FinderGetting busy with the Ubercode.
Joined: 12/28/2007
Juice: 195
Re: Re: recurring payments versus recurring orders

Zahor - You're in luck, I've written a CIM module. Check it out in contrib if you're interested. Smiling

Ryan - I've done some testing of the recurring module with the CIM module. It seems to work quite well, just using the default handler (no work for me to do! Eye-wink) but I think I found a couple bugs and have a couple thoughts for you:

1) $method isn't defined in uc_recurring_charge. I think you can just replace it with 'credit' since that's the only option, right?

$func = $gateways[$keys[0]]['credit']; //EDIT from: $func = $gateways[$keys[0]][$method];

2) $order_id and $amount aren't defined in uc_recurring_charge either. Here's what I think the charge line should look like:

$result = $func($fee['order_id'], $fee['fee_amount'], NULL);  //EDIT from: $result = $func($order_id, $amount, NULL);

3) Your default handler works well with CIM (since CIM is just like charging a credit card normally, only the number isn't stored in your database) except for one line. In uc_recurring_recurring_fee you check that the payment method is 'credit'. In the CIM module I briefly change the payment method to 'cim' so that I can handle pre-orders / partial payments. What would you think about changing that line to:

if ($order->payment_method !== 'credit' && $order->payment_method !== 'cim') { //EDIT from: if ($order->payment_method !== 'credit')

4) I noticed that you commented out part of this query:

$result = db_query("SELECT * FROM {uc_recurring_users} WHERE remaining_intervals > 0"); // AND next_charge <= %d", time());

Was that just for testing, maybe?

5) I noticed that you're logging payments to the usual uc_payments table, which makes the order balance go negative. What do you think about using a new uc_recurring_payments table instead? There could be a pane or tab on the order page that shows those payments separately. Seems a little more intuitive...although a bit more work as well...

Hope that's helpful. I'll let you know if I come up with anything else.

Best,
Chad

Ryan's picture
Offline
Joined: 08/07/2007
Juice: 15438
Re: Re: Re: recurring payments versus recurring orders

Chad, great feedback! I fixed the bugs you mentioned, but since the cim method isn't really a core feature I don't feel good about making a special exception for it in that if block. If it comes down to it, you may have to copy the functions and make your own recurring fee handler. Not a huge deal. We can brainstorm other solutions.

I love the idea of a recurring payment receipts table, too! Can't believe I didn't think of it. Eye-wink I won't put that into the beta 7 version, but put it on the feature list for the future.

chadcrew's picture
Offline
Bug FinderGetting busy with the Ubercode.
Joined: 12/28/2007
Juice: 195
Re: Re: Re: Re: recurring payments versus recurring orders

Sounds good, Ryan. I can take care of the cim method on my end...the easiest way might be for me to create a new handler, which just changes the payment method to credit briefly, calls your handler, then changes it back to cim. Alternatively, if you ever wanted to integrate support for partial payments and pre-orders into the uc_credit module, I could probably go back to leaving the payment method as credit in the cim module.

There is one other point that I think may be important. I believe that most payment gateway modules will need to mark recurring transactions as recurring when they're processed. (In Auth.net AIM this is the x_recurring_billing option). The card associations seem to require this, plus I've read some reports that setting this option can save you some transaction fees, since the recurring transactions (except for the first) won't have any CVV data and might otherwise get downgraded as a result. If anyone has any experience with this I'd be curious to get their input.

The thing I'm not sure about is how to handle an order that contains some recurring and some non-recurring items. Should the whole order be flagged as recurring to the gateway? Or should the recurring portion be charged separately, with the flag? Or can we wait until the automatic recurring charge is made (as opposed to the first charge made when the user checks out)?

I'm just not quite sure how this is supposed to work. If anyone has any experience with this, it would be very helpful.

Best,
Chad

torgosPizza's picture
Offline
Bug FinderEarly adopter... addicted to alphas.Getting busy with the Ubercode.
Joined: 08/14/2007
Juice: 4110
Re: Re: Re: Re: Re: recurring payments versus recurring orders

Just to chime in, Ryan, I'm not sure what changes you've made (haven't checked yet) - but I would suggest not making 'credit' the only method of a recurring payment. We have almost as many users who use PayPal compared to our Credit Card customers. It's more like 2/3 Credit and 1/3 PayPal... not a ton, but I think it's enough to keep the method of recurring payment flexible, if possible. Smiling

--
Help directly fund development: Donate via PayPal!

Ryan's picture
Offline
Joined: 08/07/2007
Juice: 15438
Re: Re: Re: Re: Re: Re: recurring payments versus recurring orde

Aye, the recurring fee handler in core is simply a default one to work with the credit module. The other modules will need their own handlers if they're going to handle the fees, and in that case you'd enable them in the recurring fee product feature settings as valid payment methods.

I guess where the pinch is is that right now we use a single handler to process recurring fees. I guess that means you'd need a custom module to route it to the correct one depending on their payment method selection... which is unintended. Sticking out tongue

Good feedback, though... will have to work that out as we go. Thoughts? I wasn't intending to write a hook to declare fee handlers, but maybe I'll have to so you can choose a different one for every enabled payment method? Oof.

torgosPizza's picture
Offline
Bug FinderEarly adopter... addicted to alphas.Getting busy with the Ubercode.
Joined: 08/14/2007
Juice: 4110
Re: Re: Re: Re: Re: Re: Re: recurring payments versus recurring

If it's not a ton of work, I'd say that it's a great idea to write a handler to accept any payment method. This would be good for people writing their own custom payment methods, although writing their own handlers might not be a bad idea. I think even if we have to force users to user a Credit card to buy a subscription, that's not so bad. But I like having the option there for PayPal as well and anything else that comes down the road.

--
Help directly fund development: Donate via PayPal!

Ryan's picture
Offline
Joined: 08/07/2007
Juice: 15438
Re: Re: Re: Re: Re: Re: Re: Re: recurring payments versus recurr

Oh yeah, as is it works off a hook on a per-module basis. So, any module implementing the hook will be listed in the settings menu as a recurring fee handler. You just can't specify a different handler depending on payment method right now. If you had a custom module and implemented your own hook_recurring_fee(), you could have that check $order->payment_method and kick out to a different charge function accordingly. So... it's possible, just roundabout right now. Sticking out tongue

olliemuh's picture
Offline
Joined: 03/04/2008
Juice: 23
Re: Re: Re: Re: Re: Re: Re: Re: Re: recurring payments versus re

I am a total noob to UberCart. But so far it's great.
I need to set up recurring fees but the products themselves do not have the option to set the fee.
I may have something wrong it either the install, modules used, or general "no idea what I'm doing" arenas. Please feel free to correct me.
What I'm looking for is setting up recurring fees for specific items. Example, Access to a video tutorial that requires a monthly fee. It may be subscription, but I want to be able to manually cut users off. Kind of a long story, but this fits what I am doing better.
If I could figure out where the settings are.

amaria's picture
Offline
Joined: 04/04/2008
Juice: 80
Re: Re: Re: Re: Re: Re: Re: Re: Re: Re: recurring payments versu

Don't know if you ever figured this out but it was driving me crazy too. You have to first enable recurring fees in the Product Features section of Store Configuration. Then create your product. Then go into Edit on the product and click the Features tab. That's where you can assign a recurring fee to your product. Not sure about manually cutting users off yet though.

Chisholm Technologies, Inc.
Custom software development since 1999!
www.chisholmtech.com

chadcrew's picture
Offline
Bug FinderGetting busy with the Ubercode.
Joined: 12/28/2007
Juice: 195
Re: Re: Re: Re: Re: Re: Re: recurring payments versus recurring

Ryan - I can think of two options:

1) Provide a recurring fee handler selection for each enabled payment method, as you mentioned above.

2) Provide a checkbox selection for each recurring fee handler and modify uc_recurring_process to call all enabled handlers. In this case it's each handler's responsibility to only process the appropriate orders, based on order->payment_method (like you do when you check for 'credit' in the default).

I think 2 would be easier to implement, but I'm not sure if order->payment_method is going to always be enough for a handler to know if it's the right one to process the fee. (I'm just not that familiar with how each gateway or payment method works). And there's a slight risk that if there are ever two handlers written for one payment method or gateway, then customers could get double charged if they're both enabled...but that seems unlikely to happen...

Chad

amaria's picture
Offline
Joined: 04/04/2008
Juice: 80
Re: Re: Re: Re: Re: recurring payments versus recurring orders

Chad, did you ever resolve the issue of non-recurring items in the cart with recurring items? I wrote an e-commerce system (from scratch which I'll never do again but won't complain since I was paid pretty good for it) using ASP. The items they are selling are shippable items and class registrations which needed recurring payments to enable a deposit and balance payment two weeks before the class starts. To handle both types of items, I make two types of payments for the order during checkout... Recurring payment(s) and Authorize payment for the shippable items. My shipping tool on the backend enables the store manager to mark an item as shipped which automatically sends a Delayed Capture type payment. Not sure how you would handle it with Ubercart but I need to have this functionality for another client's site.

Here's the url for the class registration site...
www.trackerschool.com

Chisholm Technologies, Inc.
Custom software development since 1999!
www.chisholmtech.com

japerry@drupal.org's picture
Offline
Bug FinderGetting busy with the Ubercode.Not Kulvik
Joined: 08/08/2007
Juice: 248
Re: Looking for uc_recurring.module testers

I put in the issue queue the postgres support. you should find it here:
http://www.ubercart.org/issue/3786/postgres_support_uc_recurring

amaria's picture
Offline
Joined: 04/04/2008
Juice: 80
Re: Looking for uc_recurring.module testers

Ryan, Is there any way to set the number of billing cycles so that it's indefinite? I'm using Chad's Authorize CIM module and was wondering about this.

Chisholm Technologies, Inc.
Custom software development since 1999!
www.chisholmtech.com

olliemuh's picture
Offline
Joined: 03/04/2008
Juice: 23
Thanks for the help. I did

Thanks for the help.
I did find out, because of your help, that if you set the billin cycles to nothing, it makes it indefinite. Hope that helps a little.

RSTaylor's picture
Offline
Joined: 04/02/2008
Juice: 99
Is indefinite really indefinite?

Great module, but I'm unsure about the indefinitely recurring charges.

I'm testing, and noticed that next billing date shows as '-' when number of billing periods = 0 (on admin/store/orders/recurring). However, there is a date there in the database, and it is correct.

In the uc_recurring_admin function, if I change:

<?php
$fee
['remaining_intervals'] == 0 ? '-' : format_date($fee['next_charge'], 'small'),
?>

to

<?php
format_date
($fee['next_charge'], 'small'),
?>

then it shows the correct date.

I also noticed that the uc_recurring_users table has 'remaining_intervals' and 'charged_intervals', but not 'number_intervals', and doesn't appear to be tied to the uc_recurring_products table (which does have 'number_intervals'). I'm not sure how that works for indefinite recurring charges, because

The cron hook uses WHERE remaining_intervals > 0.

Charging via form or cron updates the table with remaining_intervals = remaining_intervals - 1.

The charge link only shows up in admin when remaining_intervals > 0.

Did I miss something that would make it possible to charge when number of billing periods is 0? It looks like that just represents the case where all payments have been completed.

-

Another thing I noticed is that if, when configuring your product features for recurring billing, you set the Applicable Model/SKU to Any, then the model field of uc_recurring_products is empty, so uc_recurring_find_fees doesn't find the fees (because it queries by model), and so the recurring fee doesn't get setup when the order is processed. If you pick a SKU in the product feature configuration then it works.

amaria's picture
Offline
Joined: 04/04/2008
Juice: 80
Recurring Payments and Authorize CIM

I'm trying to understand how this is all supposed to work since there is no documentation that I could find. Not sure if this should go here, the Authorize CIM thread, or a totally different thread but here goes.
My setup:

  • uc_cim is setup as the default gateway in the payment settings.
  • uc_cim is setup as the Recurring fee handler in product features settings.
  • A test product priced at $19.99 is setup with recurring feature set at "When product xxxxxx is purchased, add a fee for $30.00 charged first after 0 days and every 2 days after that 9 times."

After adding the product to the cart and checking out successfully, I see the $19.99 payment on the payments pane for the order. But I don't see the initial $30 recurring payment. In the Recurring Fees pane I see the following:
ID Order Amount Next IntervalLeft Total Operations
3 26 $30.00 06/25/2008 - 21:48 1 days 10 10 charge edit delete
4 26 $30.00 06/25/2008 - 21:48 2 days 10 10 charge edit delete

I'm not really sure what that means. Why is the Next, Left, and Total columns the same for both items? Why is the Next date the same as the order date for both items?

Why didn't the initial recurring fee happen or is it supposed to happen after 1 day (24 hours) even though I specified 0 days? Did I miss something during setup?

Chisholm Technologies, Inc.
Custom software development since 1999!
www.chisholmtech.com

amaria's picture
Offline
Joined: 04/04/2008
Juice: 80
Problem Solved

Oops, on second thought I figured out why it didn't charge the recurring fee. I had not setup the cron job on my server to run cron.php . After running cron.php manually, the initial recurring payment posted. I think the reason for the additional recurring fee is because I went through a few iterations of the recurring fees settings for that product so maybe it saved multiple settings? In any case, it works with a totally new product.

Chisholm Technologies, Inc.
Custom software development since 1999!
www.chisholmtech.com