The Commerce Recurring Framework requires us to define a charge callback in hook_commerce_payment_method_info(). This architecture is probably less than ideal as we probably want to be able call from the Commerce Recurring Framework a more general API function to process a payment. I think the commerce_cardonfile module might be a good candidate but perhaps even the commerce_payment module should do this...

But in the interest of getting something working sooner rather than later (there are folks who would like payments to go through), here's my first shot at giving the Commerce Authnet module an integration with the Commerce Recurring Framework. It's not pretty yet but it's close. I still need to test it more as I'm getting weird results, but it may just be that I need to refresh my sandbox.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

R.J. Steinert’s picture

First pass. Not quite working for me yet but payments are processing. It may be an issue elsewhere in commerce_recurring module.

cosmicdreams’s picture

I've applied this patch but I still don't see it actually sending payments. I'm trying to debug now.

R.J. Steinert’s picture

Hm bummer. Check out function commerce_recurring_load_payments_due() in commerce_recurring.rules.inc. For starters, check to see if there are orders being selected when you run Cron. If there aren't any, then it's a configuration issue in your sandbox. I'm looking at one of my recurring orders from three cycles back and it has three payments on it. I'm going to debug why every recurring child order is processed every time.

R.J. Steinert’s picture

I just:

- deleted all my test orders
- added a new user
- checked out with a recurring product logged in with the new test user
- changed my server to the Invoice date on the parent order
- ran cron
- saw the child order created
- changed my server to the Payment Due date on the child order
- ran cron
- saw no payment attempted (no orders were collected by commerce_recurring_load_payments_due() as I saw in my debugger)
- changed my server to the day after the Payment Due date on the child order
- ran cron
- Received the following error after cron finished:

"Notice: Undefined offset: 1 in commerce_authnet_cim_cardonfile_charge() (line 1265 of /home/ubuntu/workspace/greenlink-pantheon/sites/all/modules/commerce_authnet/commerce_authnet.module)"

Debugging now...

R.J. Steinert’s picture

I found a problem with my last patch, using a value I thought would provide the CID id didn't so now I just take the first Card On File and assume that's what the user wants to use. We'll have to implement some "Default Card On File" functionality later in the Card On File module.

Running this test I'm having success until the last step which is causing duplicate payments:

- deleted all my test orders
- added a new user
- checked out with a recurring product logged in with the new test user
- confirmed a payment was made on the parent order
- changed my server to the day after the Invoice date on the parent order
- ran cron
- confirmed child order was created
- confirmed parent order Next Invoice field increased by interval set in Parent products Billing Interval
- changed my server to the day after the Payment Due date on the child order
- ran cron
- confirm a payment was made on child order
- ran cron again to make sure the same order wasn't picked up again for processing... It was.

So in

/**
 * Rules action callback: Load orders
*/
function commerce_recurring_load_payments_due() {
  $query = new EntityFieldQuery();
  $query->entityCondition('entity_type', 'commerce_order');
  $query->entityCondition('bundle', 'recurring_order');
  $now = new DateObject('now');
  $query->fieldCondition('commerce_recurring_payment_due', 'value', $now->format('U'), '<=');
  $query->fieldCondition('commerce_recurring_payment', 'value', 0, '=');
  $query->range(0, variable_get('commerce_recurring_batch_process', 20));
  $results = $query->execute();
  if (!empty($results['commerce_order'])) {
    return array('orders' => commerce_order_load_multiple(array_keys($results['commerce_order'])));
  }
  return array('orders' => array());
}

The $query->fieldCondition('commerce_recurring_payment', 'value', 0, '='); is not excluding orders that have payments. We have to figure out why.

R.J. Steinert’s picture

bug filed on commerce_recurring: #1421848: Document what charge callbacks should return
feature request on commerce_cardonfile: #1421832: Option to define a User's Default Card On File

R.J. Steinert’s picture

Status: Active » Needs review
FileSize
2.01 KB

It turns out the charge callbacks need to return TRUE to avoid the issue of duplicate payments. The new patch takes this into account. From my testing, this is working now.

BenK’s picture

Looking forward to testing this patch...

vlkff’s picture

I have implemented the module (a sandbox project for a moment) providing an API to authorize.net ARB and implements ARB as a commerce payment method.
See: http://drupal.org/sandbox/vlkff/1572412
It may be a good (more secure) alternative solution.

scotwith1t’s picture

I've added this patch to my commerce_authnet, i believe everything else is set up correctly, but i have hundreds of entries in my dblog about
Notice: Undefined index: in commerce_authnet_cim_cardonfile_charge() (line 1268 of /var/www/vhosts/drupal/7/sites/all/modules/commerce_authnet/commerce_authnet.module).
and
Notice: Undefined offset: 0 in commerce_authnet_cim_cardonfile_charge() (line 1268 of /var/www/vhosts/drupal/7/sites/all/modules/commerce_authnet/commerce_authnet.module).
then finally
Error occured whilst processing recurring transaction payment for order 16's - the payment method Authorize.Net CC commerce card on file charge callback reported an error.

not sure where things are going wrong...all the orders are in the orders list but are just in pending at this point...maybe there's also a rule setting that i've not got set up correctly?

scotwith1t’s picture

Wow. So, apparently this has to be turned on at admin/commerce/config/payment-methods/manage/commerce_payment_authnet_aim/edit/3 or similar (your AIM payment rule)...you have to check off "Enable Card on File functionality with this payment method using Authorize.Net CIM." for this to work. Good to know. Hope it will save a few others some trouble/time if they come across this because it wasn't clear to me. Now that I see that, I can probably report back with some useful feedback since my recurring payments oughta go through now! :)

@vlkff, i checked out your sandbox project and it has promise...will save comments for whenever you have a project page for it as this isn't really the appropriate venue.

fdefeyter@gmail.com’s picture

Hello there!

I am currently building an e-commerce website with the help of Migrate and Commerce on D7. I went to the Drupalcamp in Gent and that did help a lot...

The thing is my client has recurring products but the clients haven't been billed since 2006 in some cases!

So I need to create automatic orders and send them a mail inviting them to pay.

What do you advice me? Using rules? Or your experience showed that we can "get back in the past" in order to create all those invoices/orders/paiements?

Thanks in advance for your reply ;-)

MedicSean37’s picture

So has this patch been updated in the latest RC1 release?

DevElCuy’s picture

Status: Needs review » Reviewed & tested by the community

Patch at #7 applies clean on current 7.x.1.x-dev

benjf’s picture

the patch in #7 applies on RC1, and looks to work - although I've only done the most basic testing at this point.

Thanks!

dwkitchen’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
16.23 KB

Here is a patch for working with Recurring 2.x (http://drupal.org/node/1935040) and Card on File 2.x (#1950354: 2.x Branch for Entities and Rules for Recurring)

dwkitchen’s picture

Status: Needs review » Fixed

This is now in the 1.x branch and will be in the next dev release.

jpstrikesback’s picture

Status: Fixed » Needs work

Looks like the charge callback didn't survive the merge

Albert Volkman’s picture

Status: Needs work » Fixed

Nevermind, crosspost.

Albert Volkman’s picture

Status: Fixed » Needs work

Changing status

dwkitchen’s picture

Status: Needs work » Needs review

Added the call back, back into the payment method info hook

jpstrikesback’s picture

Looks good from my end, tho I can't test as I'm only using Authnet as a map for another payment gateway implementation.

dwkitchen’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

archimedes’s picture

Was this committed in the May 17th 7.x-1.1 release? I didn't see it in the notes, but it was fixed in dev before then.

dwkitchen’s picture

Its the Card on File 2.x update, that sits between Recuring and a payment gateway module.

archimedes’s picture

Sweet, good to know. Thanks!