I have previously blogged (http://civicrm.org/blogs/sarahgladstone/fun-and-joy-authorizenet-code-attached) and chatted about (http://forum.civicrm.org/index.php/topic,29234.0.html) about the fun and joy related to supporting automated recurring transactions in a production environment, and started the process of restructuring that portion of the code. I have made much more progress and have been using the code attached on production for about 2 weeks now. I think this approach (which I have implemented for Authorize.net) makes a good model for any payment processor that offers automated recurring contributions. You can download the code (works with version 4.3.4) HERE
My primary goals were as follows:
1) Auditability. In a production environement it is essential to have a history of all key communication with a third-party system. This should be easily searchable by an administrator or other authorized person.
2) Testability. It must be possible to test the core functionality without involving the third-party payment processing system or a web browser.
3) Repeatable, For example: If a message gets handled improperly (such as a bug in the API, some other issue that messes up the resulting contribution) it should be possible to delete the generated contribution record, and re-create it based on the data from the payment processor message log table.
My secondary goals:
4) Standardize core behavior accross various payment processors that offer automated recurring payments. Simpilfy creation of new payment processors.
5) Eliminate what my clients consider odd accounting for automated recurring payments in light of 4.3.x. In 4.3, any "pending/pay later" status contributions show as a tranaction in the "Accounts Receivable" Financial Account. When this contribution status is updated to "completed" another transaction is created to represent the movement from Accounts Receivable to the Asset Financial Account. (In this case the Payment Proccessing Account). With a one-off contribution,this is the proper and expected behavior. However, with automated recurring contributions this creates oddness for the bookkeeper. For example: They set up an automated recurring contribution of $200 per month for 12 months. (From the bookkeeper's point of view, the person "owes" $2400. ) After the first 6 payments are completed, the bookkeeper will observe that the first installment of $200. was handled as a "receivable" (because of the result of it switching from pending to completed) but none of the other installments are treated that way. So in the code I wrote ALL installments are treated uniformly: As a contribution that started out in the "completed" status. What I do is create a brand-new completed contribution for the first installment, then delete the original pending contribution. ( The other option I thought about was treating the entire $2400 as a receivable, then reducing the Accounts Receivable by $200 each month. But this idea seemed much more complex to implement)
Looking forward to getting feedback on the code and ideas here.
could you publish your code in github or another source code repository? is this meant to be an extension that you can enable or is the aim to change the core?
I cannot see a way to make this into an extension as the Authorize.net payment processor is part of core. ( I am using 99% of the Authorize.net code that ships with core, the only core logic that is overriden is the processing of the IPN/Slient Post URL messages.)
Should the Authorize.net payment processor be part of core? Should it be an extension like all other processors?
And lives its life as a normal extension
Does someone have a valid reason not to split it from the core (beside the obvious it's easier to leave it than move it out)
The 'odd accounting' mentioned in 5) above is a bug that was inadvertently created by the use of Pending status with slightly different semantics in the case of a first recurring payment versus a one-off payment. This is not something specific to Authorize.net.
We had a fix for this bug prepared for the 4.3.5 release but the logic of the upgrade code was complex enough and the impact on production data significant enough that we decided we needed to test upgrading some production databases before releasing it. It should come out in 4.3.6.
Sarah, any help you could provide in this testing would be appreciated (see http://issues.civicrm.org/jira/browse/CRM-12844).
Joe - I emailed Pradeep a backup of a database that was impacted by the issue described at http://issues.civicrm.org/jira/browse/CRM-12844. Hope this helps.
This code is now available as a native CiviCRM extension (and lives on GitHub). See https://civicrm.org/extensions/payment-processor-helper