As Michael suggested last week, I have studied how all of the payment
processors besides Google Checkout integrate with GetPaid; Michael, it
was a great suggestion! And, thanks to guidance which Christopher
Johnson provided when we talked on Friday, I have also read through the
various branches in GetPaid labeled "multiplepaymentprocessors".
(USABILITY PEOPLE: You can skip down to the "Big Questions That I
Need Feedback On" section farther down if you want
to skip the technical discussion.)
As a result, I now have a more complete picture of how the various
GetPaid payment processors are designed. To keep things straight, I
sketched out this rough diagram in Inkscape this afternoon:
http://rhodesmill.org/brandon/static/2009/getpaid-overrides.png
Red text in the diagram indicates the presence of a ZCML override of
some sort. Note that I have left out extra steps that might be present
in the wizard, like shipping options; when present, such steps would sit
between the "Address Info" and the "Review & Pay" pages in the diagram.
Payment Processors, and How They Work
-------------------------------------
Taking the diagram from top to bottom:
* Google Checkout:
The payment processor provides its own copies of the shopping cart
view and shopping cart portlet, so that it can draw a pretty "Google
Checkout" button on each of them. The buttons point at a view named
"/google-checkout" on the Plone site, which has no associated
template but instead redirects directly to Google itself.
OPEN QUESTION: It is not clear to me why the checkout buttons do not
point at Google directly instead of going through the extra view, but
I see Google Analytics parameters being constructed on the way that
might have something to do with it.
* ClickandBuy / PagSeguro:
These both provide their own @@getpaid-checkout-wizard view that
removes all of the normal functionality, and shows a big button that,
when pushed, sends the user to an off-site checkout process.
OPEN QUESTION: This approach competes directly with the Google
Checkout approach. Which is better: providing a special checkout
button for "Checkout"? Or, letting them visit our normal checkout
URL then asking them to click off-site? The former requires one less
click from the user; the latter gives them a bit more warning that
they are leaving. Should we rewrite all three payment processors to
use a common approach, and then provide an admin config option for
whether a store owner wants the extra "Click here to checkout" step
added or not?
* PayPal:
This also provides its own @@getpaid-checkout-wizard, but the view
simply does an immediate redirect to PayPal.
OPEN QUESTION: Like with Google Checkout, the question is, why?
Because it was easier than overriding the "Checkout" buttons? Or
because the extra step lets a few last variables and parameters be
put into place before the customer arrives at PayPal?
* Luottokunta / Verkkomaksut:
These processors only change the last step of the default checkout
wizard. They simply provide an alternate form for the last view,
named @@checkout-review-pay, that asks for some fields that their
particular payment processors need to operate.
* Ogone / PxPay:
These payment processors do a good deal more violence than the
previous two we looked at. Like them, they let most of the checkout
wizard views complete their job, and then just override the final
@@checkout-review-pay page. But instead of presenting a slightly
adjusted form, they actually redirect the user away from the Plone
site altogether, so the customer's credit card information can be
entered on the remote site.
OPEN QUESTION: Why do I call these two more "violent"? I think it's
because of how painfully they abuse the idea of an IPaymentProcessor.
Instead of simply dropping the idea altogether and performing their
redirects directly - which is what a view is for, right? - these two
payment processors have their @@checkout-review-pay views call the
authorize() method of a PaymentProcessor object that then - I warned
you that this was painful, right? - performs the redirect itself!
They put, in other words, view logic inside of an interface that's
supposed to process a credit card and return an actual result.
* nullpayment / AuthorizeDotNet / PayFlowPro / PaymentTech
These are the well-behaved payment processors that actually work as
GetPaid intended. Note the happy lack of red text from their area of
the diagram! They accept payment information and try to get the
payment processed, and leave it up to the PloneGetPaid views to
report back to the user whether their purchase worked.
So, there you have it! No fewer than six separate techniques are used
in GetPaid payment processors for what are really amounts to four
separate situations:
1. Off-site processors that provide their own checkout wizards
(Google Checkout, ClickandBuy, PagSeguro, PayPal)
2. Off-site processors that let Plone collect the shipping info
(Ogone, PxPay)
3. Normal payment processors that need a few payment fields adjusted
(Luottokunta, Verkkomaksut)
4. Normal payment processors that can use the default payment page
(nullpayment, AuthorizeDotNet, PayFlowPro, PaymentTech)
So, what about the "multiplepaymentprocessors" work?
Multiple Payment Processors
---------------------------
The "multiple payment processors" branches seem focused on processor
categories 3 and 4, as given in the above list: the processors that
require GetPaid to ask for the credit card number on-site. For these,
it introduces a new registration system. Instead of simply registering
themselves as providing IPaymentProcessor, these new-style payment
processors would have to actually use a custom ZCML registration that
looks like:
<paymentprocessors:registerProcessor
name="..."
i18n_name="..."
selection_view="..."
review_pay_view="..."
thank_you_view="..."
settings_view="..."
/>
The basic idea here is that many payment processors can register
themselves this way. The store owner will be shown all of them on his
Site Setup page, and be asked which he wants to use. If he only selects
one, then that is the one that users are sent to directly. But if he
selects several, then a new @@checkout-payment-method step is placed
before the final @@checkout-review-pay step, and the user is shown a
pretty button for each available checkout method (that's what the
"selection_view" shown above is for), and has to select one.
And the final checkout form, when they get there, can be possibly
customized to have extra or different fields from the normal one. That
seems to be what the "review_pay_view" means in the registration example
above: it's a way, without an override, for a payment processor like
Luottokunta or Verkkomaksut to adjust what the final view contains.
I am not sure what I think about special ZCML declarations; it seems to
me like the same information could be provided much more simply through
the adapter-registration mechanism we already use, and that class
properties with names like "thank_you_view" and "settings_view" would do
a fine job of pointing at the views that the payment processor wanted to
provide, without needing any ZCML. But that's probably my Grok
background showing through, and maybe there are view configurations done
behind the scenes here that I've not studied yet.
What does everyone think? If something can be done simply enough in
code, should ZCML be used or not?
Either way, it looks to me like the "multiplepaymentprocessors" work is
a great candidate for getting rid of the overrides required by category
3 payment processors, as given above, and for letting users choose their
favorite payment processor when it's okay with the site owner.
That, of course, just leaves categories 1 and 2 as problems.
Handling Off-Site Checkout Wizards
----------------------------------
Right now, the series of steps that the on-site checkout wizard supports
seems kind of hard-coded; in the "CheckoutController" it says (in the
new "multiplepaymentprocessors" branch):
steps = ['checkout-address-info', 'checkout-select-shipping',
'checkout-payment-method', 'checkout-review-pay']
What if this list was something built dynamically? What if the default
was something like a series of views like this:
100 'checkout-address-info'
200 'checkout-select-shipping'
300 'checkout-payment-method'
400 'checkout-review-pay'
where plug-ins could provide steps of their own, like:
150 'checkout-shipping-company'
Maybe inequality invariants would be better than static numbers; but
static numbers work pretty well for the Ubuntu package managers who
build all those /etc directories, I'll note. But whichever way we
established order among the steps, the act of building the list
dynamically could have several advantages.
One of them would be that none of the remaining payment processor types
would need overrides! "ClickandBuy", for example, could just say:
050 'checkout-clickandbuy-button'
and the view that shows the "Check out at ClickandBuy" button would show
up in front of the user before anything else in the wizard - and then
the button could take them far away and not return them, meaning they
wouldn't encounter any of the rest of the wizard. This could handle
Google Checkout, ClickandBuy, PagSeguro, *and* PayPal, *if* we were
willing to tell the people using Google Checkout and PayPal that they
have to use a you're-leaving-the-site splash screen like ClickandBuy and
PagSeguro. Actually, maybe that wouldn't be necessary; maybe they could
provide a set of "redirect" views that could be dropped in place if the
store owner opted not to have a two-click process where one would work:
050 'checkout-paypal-redirect'
Processors like Ogone and PxPay would put their redirect (or
leaving-this-site click-this-button) page later in the process, after
the shipping information has been collected:
350 'checkout-pxpay-redirect'
The one thing that such a pluggable-pages scheme would *not* fix is the
situation, like the Google Checkout design today, where the "Checkout"
buttons on the shopping cart view and shopping cart portlet both need to
be re-drawn to "look like" the checkout buttons for the selected payment
processor. If we want to support that, then we need to do work
"outside" the standard wizard, like the work I announced last week that
I did experimentally in my "brandon-no-overrides" buildout: we need
those buttons to become views that payment processors can override.
Big Questions That I Need Feedback On
-------------------------------------
The big outstanding questions I have right now are:
* It's neat for users to be able to choose among payment processors
like AuthorizeDotNet and PayFlowPro, that both plug in right at the
end of the normal checkout wizard. But what about off-site services
that provide their own wizards, like Google Checkout? Should users
be able to choose between Google Checkout and AuthorizeDotNet?
I would *love* for this to be answered as a usability question,
*not* a technical one; a good design is possible here either way we
answer the question. The usability question that is raised is this:
the choice between AuthorizeDotNet and PayFlowPro can be asked right
at the end of the wizard, before the credit card information is
demanded. But the choice given to the user between using Google
Checkout and AuthorizeDotNet would have to be asked immediately,
before the first normal page of the wizard was even shown. Should
users in a multiple-payment-processors situation (a) *always* be
asked which they want to use *before* entering the wizard, or (b)
should the question "float" so that it's asked right before it
becomes important, but otherwise as late as possible, so that it's
asked before the other wizard steps if, say, Google Checkout is one
of the options, but late in the process if it's just AuthorizeDotNet
and PayFlowPro?
I'd love to do (b) because it seems the "real answer" that, if done
right, lets store owners give users the maximum amount of choice
when it's what's wanted. But I'm open to counter-arguments.
* Again, a usability question: do store owners deserve the right to
avoid a "click here" screen by having the cart "Checkout" button say
"Check out with Google Checkout" and go right there? Conversely:
should every off-site processor support, if the store owner wants
it, a separate "click here to leave" screen that follows the normal
"Checkout" button instead of subverting it?
I think this answer should probably be "yes", and I think a
reasonable design will result. Let me know if this matches what
other people want; you guys have used this a lot more than I have!
* I assume that users partway through the checkout process with
PayFlowPro should be able to back up and re-start with Google
Checkout if they suddenly realize that's what they want to do?
IF the above usability questions are answered like I expect, then I
might have to rescind the distinction that I tried to draw in my
"brandon-no-overrides" experiment between Wizards and Processors,
because that would create an ugly situation where users whose store
owners had been very liberal would have to *first* choose their Wizard,
*then* choose their back-end Payment Processor if they choose the
built-in Wizard; or an ugly combined form would have to be created. I
would like to avoid either of these situations! If we decide we want
true flexibility here, then I think we need to abandon my "Wizard"
concept and just talk about "Payment Processors that redirect the user
somewhere else" versus "Payment Processors that let GetPaid do most of
the work, then just verify the credit card."
Apologies For Stuff I've Gotten Wrong
-------------------------------------
Today was my first time looking at most of these payment processors, and
I've probably gotten a bit mixed up about how some of them work. If you
find I've misunderstood anything above, then just reply and point out
how this first impression of my differs from the reality. I want to
make sure that all reasonable payment processor designs become easy as
we re-factor how they are registered and deployed!
Next Steps
----------
As usual, given the size of this email and the questions it asks, I'll
wait a day or two so that people have time to digest it and respond.
Then, unless the responses really surprise me and merit debate and
discussion, I think my next step will be to try inventing and
documenting - but maybe not implementing until I get feedback on the
draft documentation? - a straightforward registration scheme that
supports all the kinds of payment processor we've got. I'll call the
draft "How to Write a Payment Processor", with the idea that we focus on
exactly that: what will payment processors look like to the person who's
*writing* them, in a way that's flexible enough to support the whole
spectrum of techniques we've listed above. Then it'll be a simple
matter of adjusting the GetPaid core, the Plone Product, and the various
change processors to match the new standard. :-)
--
Brandon Craig Rhodes [email protected] http://rhodesmill.org/brandon
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"getpaid-dev" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/getpaid-dev?hl=en
-~----------~----~----~----~------~----~------~--~---