chris, et al, i took another look at uc_cim http://drupal.org/project/uc_cim for handling recurring payments - would like some help in getting it to work with uc_recurring.
after getting the error message "A handler for processing and renewing recurring fees cannot be found for the cim payment method" and looking through uc_cim.module there was no implementation of hook_recurring_info() ...so i added to uc_cim.module
function uc_recurring_uc_cim_recurring_info() {
$items['authorizenet_uc_cim'] = array(
'name' => t('Authorize.net (CIM)'),
'payment method' => 'credit',
'module' => 'uc_cim',
'fee handler' => 'uc_cim',
'renew callback' => 'uc_recurring_uc_cim_renew', //this callback is already defined by uc_cim
'process callback' => 'uc_recurring_authorizenet_uc_cim_process', // this callback is a wrapper to uc_cim.module::uc_cim_charge()
'saved profile' => TRUE,
'own handler' => FALSE,
'menu' => array(
'cancel' => UC_RECURRING_MENU_DEFAULT,
), // Use the default user operation defined in uc_recurring.
);
/* this fee handler should not be dependent on uc_authnet_cim_mode since uc_cim is not dependent on uc_authorizenet
why does both uc_recurring_hosted.module::uc_recurring_hosted_recurring_info() AND uc_recurring.uc_authorizenet.inc::uc_recurring_uc_authorizenet_recurring_info()
set $items['authorizenet'] key?
if (variable_get('uc_authnet_cim_mode', 'disabled') != 'disabled') {
$items['authorizenet'] = $items['authorizenet_uc_cim'];
}
*/
$items['authorizenet'] = $items['authorizenet_uc_cim'];
return $items;
}
uc_recurring.module::uc_recurring_get_recurring_info() makes a call to ::uc_recurring_includes(), which hard codes an array
$modules = array('uc_authorizenet', 'test_gateway', 'uc_credit', 'uc_payment_pack');
this should be patched to include 'uc_cim' - or better any enabled payment method. anyway, back to uc_recurring_get_recurring_info()
foreach (module_implements('recurring_info') as $module) {
uc_recurring_uc_cim_recurring_info() will not be returned by module_implements() but uc_cim_recurring_info() will... yet
$func = 'uc_recurring_'. $module .'_recurring_info';
if (function_exists($func) && $result = call_user_func($func)) {
$data[] = $result;
}
will exclude uc_cim_recurring_info() from inclusion in $data[]...
so how is uc_recurring.uc_authorizenet.inc::uc_recurring_uc_authorizenet_recurring_info() being included in $data[] while uc_recurring_uc_cim_recurring_info() is not?
Comments
Comment #1
torgospizzaSounds to me like, the hook is there, but for some reason either the dynamic function doesn't exist or the $items being returned is NULL? I'd like to test your code out. Can you roll a patch, or did you just place these at the end of the module?
Comment #2
univate commentedThat function is a hook [hook_recurring_info()], so you need to use it as a hook, ie: modulename_recurring_info() so it can be found:
I would also change all your callbacks to start with uc_cim, as that is what the module name is and you will only run into problems prefixing other modules namespaces at the front of your functions.
As for why do you need to declare $items['authorizenet'], because uc_recurring will look for a item with the same key as the gateway, which in the case of authorizenet payment gateway module is "authorizenet", that could be different for uc_cim (I haven't looked at the code and if it declares a different gateway?"
Comment #3
univate commentedThat hook is well documented in uc_recurring.api.php as its the key to make recurring payments work.
Comment #4
jaypark commentedchanged uc_cim_recurring_info() and moved it to uc_cim.module.
i'm no longer getting the error "A handler for processing and renewing recurring fees cannot be found for the cim payment method" but still getting the "Your order cannot be completed, because we could not process your recurring payment. Please review your payment details and contact us to complete your order if the problem persists." error. this message is returned in uc_recurring_product_order() which calls uc_recurring_product_process_order(), in which there are only 2 statements that return FALSE. so the failure must be from
...however, drupal_set_message() isn't called from within uc_cim_authorizenet_uc_cim_process(), at the first line within that function. even if the call by reference is causing the failure why wouldn't the $order and $fee objects get printed?
Comment #5
jaypark commentednote that the checkout order actually succeeds and no errors are returned to watchdog or the order messages. a.n cim payment profile history also shows a successful transaction. i'm wondering if uc_cim can use the existing authorizenet_cim fee handler to process the recurring fees, since uc_cim.module does everything else with respect to cim services - and quite well.
edit: chris, if i get down on my knees and beg you to take a look at uc_cim, will you? :P maybe throw some cashola in your direction? what's it going to take mate?
uc_cim was supposedly working with uc_recurring, but i guess stuff got broken when uc_recurring was taken out of uc core. i'm not familiar with what got changed.
Comment #6
torgospizzaWe might also be willing to put some cash toward it. I'd also like to help, although I'm not as familiar with the module as others.
Comment #7
jaypark commentedmeh. got it working :P
Comment #8
torgospizzaWoohoo! Care to post a patch?
Comment #9
univate commentedThose function names are still very strange names to me:
Something like:
Would make much more sense and readable to me, if I was to look through that code for the first time.
I have glanced at the uc_cim module, I have an issue with that module, I think it would be fair greater to see effort focused on one solid authorizenet module instead of multiple modules, the reality is that the one in core is always going to get more users, so that seems like the better option to focus attention on. There are features in uc_cim that really shouldn't be there as they are not specific to that gateway and would have been so much better if the developers could integrated then into modules like uc_recurring and other ubercart modules where everyone using other gateways can benefit from the features.
That said I am potentially available to do some (paid) work on this if you still need help - otherwise if you have made progress do post your work, a patch to uc_cim makes the most sense here.
Comment #10
torgospizzaAgree completely.
I'd personally love to see the patch made to uc_cim first, to get it working, and then see if we can get that work (and the rest of the advanced CIM functionality) back into core. It really doesn't make sense to have both modules, especially when core authorize_net functionality in UC provides some level of CIM integration. I don't like that uc_cim provides its own cc form in checkout, either. Things like that which could be merged as a 2nd step of the process would make things much easier to focus efforts on.
It also removes one point of failure for things like uc_recurring; instead of making sure uc_recurring works with both core AND uc_cim, we can focus on just getting it to work with core.
Let me know what I can do to help. I'll try taking a look at some of the other CIM issues and see which ones I can try to patch in core, but if I do, I will put that into another issue so as to not hijack this one.
Comment #11
jaypark commentedchris, i took a look at your securepayau module, which helped.
"I think it would be fair greater to see effort focused on one solid authorizenet module instead of multiple modules"
uc_cim has no dependency on authorizenet module; in fact i have it disabled. [edit there is nothing the core authorizenet module does that uc_cim doesn't do better... there are sound reasons for choosing cim. edit]
"the reality is that the one in core is always going to get more users, so that seems like the better option to focus attention on"
true... no code was edited within ubercart [edit and a minor patch for edit] uc_recurring for this patch so it might be simpler to get into ubercart core. most of the heavy lifting had already been done by chadcrew, et al. they did excellent work with the a.n cim api (although i saw a lot of the code was "borrowed" from authorizenet already in ubercart core).
"I don't like that uc_cim provides its own cc form in checkout, either."
true, a lot of their checkout code is directly copied from uc_credit.
"That said I am potentially available to do some (paid) work on this if you still need help"
:P haha! i will know for sure that it works after the production site (currently using arb, already heading towards 1k paying members after just a few months in operation) gets an extra boost this coming month from a big marketing campaign. cim services will be needed to automate things that arb api wasn't designed to handle.
i was just really surprised to see cim in the state it was in (no updates since ubercart 1.6?), given that authorizenet is the biggest gateway (for real merchant accounts) in the us and cim is clearly their best service for recurring products or any repeat biz.
best to you and yours mate, jay.
[edit let me say that this hasn't been tested with a production a.n account yet - but everything works with a.n test account... production tests are next step. edit]
Comment #12
torgospizzajaypark,
I'm really interested in getting your code as well. Let me know if I can help with any tasks and testing. We have a live a.n. account ready to go, could probably get a production test setup there as well.
Please post some code when you can, would love to get testing! Thanks for your hard work on it.
Comment #13
mr.andrey commentedsubscribing...
Comment #14
interestingaftermath commentedsubscribing
Comment #15
jaypark commentedthere were additional errors fixed:
1. order id (and payment) was being set to the orginating fee order id, not the recurring fee order id [edit so the recurring payment was getting applied to the originating order, not the recurring order and the outsanding balance would not trigger role renewal edit]
2. fee object->array type mismatch
3. show the switch payment form for orders that originate recurring fees only
also automatically call uc_recurring_renew() when the payment profile is updated or added - this is only applicable to recurring orders that grant roles for subscription sites [edit and the subscription has expired due to non payment or cancellation - on user login, the customer is directed to the manage credit card page to update/add payment profile edit]
almost ready for prime time... will probably upload the module at uc_cim in a few days.
Comment #16
jaypark commentedthread moved to uc_cim
Comment #17
torgospizzaGreat news! Looking forward to it.
Comment #18
MixologicI've been digging into all the various threads here regarding getting the Authorize.net CIM stuff working, and am seeing a need for a level of abstraction that could make for bunny rabbits and rainbows in the long run.
uc_recurring does a great thing, in that it abstracts recurring payments away from the gateway that actually implements those recurring payments, such that I can swap out gateways, but not have to have a different UI for assigning recurring payments to products, selecting recurring payments during checkout, or allowing users to manage their own recurring payments (cancel/change card data etc).
uc_cim addresses the issue of secure customer data storage, but its only geared towards one specific gateway, which will help out those of us who want to use authorize.net's CIM service, but doesnt help any other CC tokenization or data vault implementation.
What I propose is that we either
The features that Im seeing that are the most universal with credit card tokenization solutions pretty much boil down to storage of CC data (card#, cvv, Expiration, Name on card), Billing address for the cards, the customer (id, name, etc), and *sometimes* shipping profiles as with CIM.
This abstraction would make for a consitent UI for customers, and a consistent API for other modules allowing for:
Probably More?
There are many other customer data storage solutions out there beyond just CIM, so this would allow for much easier implementation of those gateway interfaces e.g.:
Additionally we can create a test customer data storage gateway such that one can test this sort of functionality without actually having a gateway plugged in.
Im moving this back to uc_recurring since it appears as though the maintainer of uc_cim isnt actually doing anything with it, plus I'd like to ensure Univate's input on this matter..
Comment #19
univate commented@Mixologic - uc_recurring is in part already doing what you are after, with the right gateway (e.g. Auth CIM) its possible to use an existing details stored in a recurring fee to charge any amounts at anytime. Its just the front end requirements that need to be developed - so its possible to develop a module now to handle "single click checkout" using uc_recurring as the backed assuming you are using a gateway like Auth.net CIM that supports charging amounts to a stored profile. There certainly are other gateways that support these features I have used two in Australia uc_securepayau and uc_eway.
The way this is being handled in uc_recurring is the payment gateway module is in control of how recurring profiles are setup and charged when renewals are due. So there are two core functions that happen between uc_recurring and gateways:
* when a users checks out with an order, make a recurring fee out of it
* with this order and recurring fee, charge the user
With these two functions in place, we can build a lot of functionality on top without needing to know anything about the gateway or where the payments are coming from.
I'm not sure if you are suggesting that we actually store CC#'s (no-one is ever allowed to store cvv anywhere including in Auth CIM, I would encourage anyone dealing with online payments to read the PCI spec) - but heading down this path is a bit of a minefield, I think its best to deliberately leave in a technical hurdle to storing CC details (it is possible to do it with uc_recurring with a small amount of code now - the time consuming part is auditing your code and system for all security requirements). I know that I don't want my credit card details on some system where the site builder/developer does not have the required security skills/knowledge to protect my details.
Although having said that I certainly would like to have CC expiry dates stored somewhere useful, so we can monitor for upcoming details about to expire. But there is already another issue related to this specific problem.
Comment #20
MixologicDefinitely not suggesting we store cc#'s.. I was more getting at the "single click checkout", and more specifically a standarized UI. If we are storing credit cards with a tokenization provider we should be able to allow users to add/update/delete their cc's from their user page (much like uc_cim does), and re-use those cc's on checkout.
Comment #21
univate commentedAt the moment updating credit cards in uc_recurring is an operation that can be provided by the gateway, not sure if its working in Auth.net CIM, but in the gateway I work with uc_securepayau I have created an 'update' operation that admin or users can use to update the cc details stored.
Its possible to streamline this although the form to enter the credit card details is the simple bit and we can already reuse the cc form form uc_credit, the complex part of the interaction with the gateway.
Comment #22
jaypark commentedmix, you have some good points. with respect to abstracting the view layer (ui), in fact there is already a lot of code in uc_cim duplicated from ubercart for the user forms.
"Im moving this back to uc_recurring since it appears as though the maintainer of uc_cim isnt actually doing anything with it, plus I'd like to ensure Univate's input on this matter.."
the maintainer did acknowledge in an email that uc_cim isn't being actively maintained and there were no plans for that changing. even so, this thread is specifically about uc_cim, uc_recurring issues.
i've since posted my patches to uc_cim to bring it current with current dev versions of uc_recurring and ubercart:
http://drupal.org/node/925860
excluding an additional patch for a bug where an update to the order status doesn't always grant the purchased user role after checkout, this code is in production.
Comment #23
jaypark commentedunivate has done a good job abstracting the uc_recurring application logic from the payment gateway. in fact, i only had to add 1 line of code to uc_recurring.module to get uc_cim working.
maybe a new thread within ubercart to address your requests would be appropriate. what mix is getting at is an interface that would best be handled by ubercart core.
Comment #24
entrigan commented@jaypark, #23,
Can you explain more about why you need to add a uc_cim_check_fee_record($fee); call in uc_recurring module?
Comment #25
univate commentedI had a look at the uc_cim code and can't see any reason why there is a need to patch uc_recurring to do anything.
The uc_cim_check_fee_record() does two things:
1) sets the order status to "complete"
2) sets the uid for anonymous purchases
Firstly uc_cim should not be setting the "order status" this should be done through CA when an order is paid and if not shippable. This is already setup and working with uc_recurring when an order is renewed.
Secondly the uid is set for anonymous purchases in uc_recurring through the hook_uc_checkout_complete()
Comment #26
univate commented