News:

Support the VirtueMart project and become a member

Main Menu

Why don't payment modules extend 'ps_payment.php'?

Started by mwmills, December 22, 2006, 08:06:48 AM

Previous topic - Next topic

mwmills

Hello,

I'm working on some changes to support delayed capture and other things to the LinkPoint payment module.  I see that delayed capture is already supported in a couple of other modules, but I would like to standardize the whole thing and add a few more interfaces.

It looks like 'ps_payment.php' is basically used as a model for the interface that payment modules need to implement.  But why don't the payment modules actually subclass 'ps_payment.php'?  Is this just an oversight?

If there's no problem, I would like to propose the following additional interfaces in ps_payment.php, and that payment modules should subclass ps_payment.php.  The additional interfaces that I'm thinking of right now are:

1. capture_payment() - captures a previously authorized payment (A couple of other modules already support this, and support is currently hard-coded into ps_order.php).

2. getAuthCaptureMode() - Returns the current 'payment mode' - i.e., capture on checkout, delayed capture, or authorize only (so you can process the capture in a backend software system.)

3. getCaptureOnStatus() - Returns the status (like change to 'Shipped') that should trigger the delayed capture.

4. getTranResults() - Returns an array of transaction results in a gateway-independent format ('AUTH_CODE', 'AVS_CODE', 'TRAN_ID', etc.)

Please let me know if anyone has any comments on this...

Mike Mills




teemu_m

Quote from: mwmills on December 22, 2006, 08:06:48 AM
I would like to standardize the whole thing and add a few more interfaces.

This subject is very complicated, because there are so many different kind of payment methods. I have developed FIPN_VM - Finnish Instant Payment Notification payment method add-on for VirtueMart and Direct Deposit payment method add-on and yet I don't have any idea of what you mean by "delayed capture". Maybe we use different terms for the same thing or maybe the payment methods we try to implement are so very different. I do agree that VM could use a standardized, more elegant and more modularized payment method implementation. But I would hate to see that the standard limits development of some payment methods while favoring others.

Quote from: mwmills on December 22, 2006, 08:06:48 AM
It looks like 'ps_payment.php' is basically used as a model for the interface that payment modules need to implement.  But why don't the payment modules actually subclass 'ps_payment.php'?

The Gang of Four says: "Favor object composition over class inheritance."

Anyway - AFAIK an interface is a "list of methods" which its instances have to and should be able to implement. Therefore, in this case, the VM payment method interface should not include tens of class methods which are very specific to some particular payment method or small group of similar payment methods. The interface should only have class methods which are common to all payment methods.

IMHO the biggest problem,  not just for VM but all PHP shopping carts, is that their payment method implementations are closely tied to the particular shopping cart application. Why every payment method has to be coded again and again for different shopping carts? In my part I have tried to avoid this while developing FIPN. It therefore consists of two separate parts:

  • FIPN is an application independent class hierarchy containing core functionality to perform communication between an online merchant and online banking gateways of finnish banks.
  • FIPN_VM is an adapter layer between FIPN and VirtueMart.

mwmills

Quote from: teemu_m on December 22, 2006, 11:27:44 AM
This subject is very complicated, because there are so many different kind of payment methods.
...
But I would hate to see that the standard limits development of some payment methods while favoring others.
...
The Gang of Four says: "Favor object composition over class inheritance."

I don't think you understand what I am saying - or perhaps, you mistakenly presume that _I_ don't understand what I am saying.

First, regarding your quote from the Gang of Four:  Please note that the current situation does not use either composition or inheritance.  It uses "copy my style" and hard-coding.

Second, it doesn't apply because both the payment and shipping infrastructure are classic cases for polymorphism, in which case a standard interface is required.

Yes, there are a number of different 'types' of payment methods - and VM already recognizes that to an extent, as it currently supports 'Credit Card', 'Use Payment Processor', 'Bank Debit', 'Address Only / Cash on Delivery', and 'PayPal (or related)' payment types.

But at least within a certain 'type' of payment, the interface very much could (and should) be standardized, and driven from the cart polymorphically.

VM already does that to an extent.  But the support for delayed capture is hacked in, and I would like to standardize that, along with a few other things.

What is delayed capture?  It is the process of getting an authorization for the purchase amount at time of checkout, and then - later - capturing the funds at the time of shipping (or as appropriate.)  With VM, the idea is that when you change the status of an order to "Shipped" (or whatever you configure), that would then trigger the capturing of funds, using the transaction ID of the previous authorization.

You're not really supposed to capture funds from a credit card until the item is ready to be shipped.  For many shops that ship same day, it isn't really an issue and capture-on-checkout is fine.  But capture-on-shipping is more accurate and in line with credit card association rules.

Second, there is the need for authorization-only transactions, in which case the funds are never captured by VM.  There are multiple uses for this.  One would be the case where a merchant has an existing merchant account terminal, and would just like to key in the credit card info (minus the verification value, though.)

In my own case, I have interfaced VM with StoneEdge Order Manager, as it provides a whole lot of features that VM currently lacks.  StoneEdge has the ability to connect with a variety of payment gateways, including LinkPoint, and can be configured to capture the funds at the time of shipping.  This is useful, as we often have to adjust orders (change shipping option, etc.), which affects the total order amount.  With authorization-only in VM, I can import my orders into StoneEdge, make any adjustments, and capture funds as labels are printed.

In any case, yes, the interfaces in question need to be well thought out.  And I also agree with your comments about making the payment code (and the shipping code too, for that matter) cart-independent as much as possible.

Regards,

Mike Mills

teemu_m

Quote from: mwmills on December 23, 2006, 09:13:19 AM
I don't think you understand what I am saying - or perhaps, you mistakenly presume that _I_ don't understand what I am saying.

It is obviously me who didn't understand :)

Thank you for the additional information about delayed capture - I find it very interesting and it certainly did widen my understanding of the problem.

Quote from: mwmills on December 23, 2006, 09:13:19 AM
And I also agree with your comments about making the payment code (and the shipping code too, for that matter) cart-independent as much as possible.

Since your are obviously a very skilled developer and since you have studied the problem of payment methods, have you ever thought of separating the payment methods to an entirely independent package, which could be utilized thru an API not just by VM but by any PHP-application?