On Sat, May 18, 2002 at 12:28:04PM +0100, Steve Keay wrote:
> We also use datacash and it seems to work quite well - post the CC
> number, amount, etc.,  via https and they return "yes" or "no" with a
> transaction tracking number.

A firm I used to work for (sadly "dust to dust, ashes to ashes, liquidity to
liquidation") used datacash, "and it was good" (not that we every really quite
got live paying customers).

However, we also used perl talking to Oracle. And we had this nasty revelation:

BEWARE OF TRANSACTIONS

We figured that we had made a nasty race condition in our system when the
punter pressed the final "pay for it"

user
     -> http
        request  ->
                    our server
                    perl -> Oracle

At this point the oracle stored procedure started. Being a transactional
database, the various stored procedure calls were doing things in one
transaction (which I believe is that default, although I'm not sure if that
is Oracle's default, or the default setting on PS/SQL programmers)
The stored procedure initiated a call onwards to Datacash (using more perl)
to make the credit card transaction.

                            Oracle  -> perl
                                            -> encrypted
                                               http request  ->
                                                                Datacash

at this point, Datacash does stuff, parts the customer from their money, and
initiates the return transaction. This could take several seconds:

                                               encrypted     <-
                                               http response
                    our server
                    perl <- Oracle  <- perl
                            (commit)
        http     <-
     <- response
user

All well and good.

But, what happened in our system if the user pressed the browser stop button
somewhere in the several seconds where we're waiting for Datacash?
We figured the following "and were sore afraid" (briefly, but glad we
rewrote things to avoid this problem):

[user presses stop.
 browser drops TCP connection]

                                               encrypted     <-
                                               http response
                    our server
                    perl <- Oracle  <- perl
        attempt
        http     <-
     !! response

At this point the perl script tries to write its response. The user has
caused the browser to close the TCP connection, so the server gets a
SIGPIPE and unceremoniously kills the perl script.
Because the perl script is killed, and does not exit cleanly, it drops
the connection to Oracle. So Oracle rolls back cleanly. That's what Oracle
is designed to do.

Erk. Because what we now have the following situation:

Datacash has processed our transaction completely, and has removed money
from the customer.
Our Oracle database has no record of this ever happening.

We solved the problem (IIRC) by having a commit as we were about to initiate
a chat with the Datacash server, and a second commit after we'd just
completed the chat with Datacash, so that we would be able to spot any
partial or late aborted financial transactions.

I just thought that I should warn you, as datacash makes it easy to set
things up, and you may not be aware of this subtle gotcha.

Nicholas Clark
-- 
Even better than the real thing:        http://nms-cgi.sourceforge.net/

Reply via email to