views:

684

answers:

5

What's the best way to prevent a user from making duplicate credit card transactions? Be it by clicking the submit button too many times, or by navigating back from the receipt page and clicking the submit button again.

+4  A: 

Couple of ways:

  1. Disable the button immediately after clicking it.

  2. Have a batch process to remove duplicates from settlement later in the day, so they won't get charged.

  3. Use some kind of modal window to stop the user from navigating till the credit card transaction is processed. Jquery has block.UI plugin that can work for you.

CodeToGlory
2 is out because it would prevent the user from getting charged twice, but not us as we get charged per each transaction, whether it gets completed or not. 1 and 3 prevent the user from clicking submit twice, but what if they use the back button?
NYSystemsAnalyst
block UI wont let you go backhttp://malsup.com/jquery/block/
CodeToGlory
+1  A: 

Add some sort of synchronization mechanism to your back-end system so that only one thread may be processing 'to be charged' records into your underlying datasource at any one point in time. Inside this synchronized region, add a check to ensure that the charge that is about to be processed does not already exist in the datasource. If such an error does occur, make sure to output some sort of graceful message to the customer - at least it won't be fatal on the back end.

It also helps to add a 2nd layer of protection at the UI level, as suggested by CodeToGlory. This will minimize the number of times that this occurs.

tehblanx
+8  A: 

You could generate a unique value, and put it in a hidden form. Before you charge the credit card make sure this unique value has not been processed already. This coupled with CodeToGlory's suggestion of disabling the button should resolve both of your use cases.

JoshBerke
+3  A: 

Most banks require that you provide unique order ID, so there is no way of charging twice for the same order.

Now, if you're asking for prevention of duplicate submit, the standard way is the Post/Redirect/Get pattern. You might also combine that with deactivating submit button with JavaScript.

You'd have:

  1. order_form.aspx, generating unique order ID and submitting by POST to
  2. proces_order.aspx doing the actual work, emptying the basket, and then redirecting to
  3. thankyou.html

Now, if user clicks reload, only reloads static thankyou.html. If he chooses to click back, get's back to order_form.aspx, but his basket is already empty. Should it somehow be cached, it'll get cached with the same order ID, so no risk of charging twice there.

vartec
This won't solve all the concerns, but coupled with the other suggestions I think this would be a good solution
JoshBerke
Actually the gateway requires a unique TRANSACTION id, which many people just use the order-id for. But that's not a good solution because one order may involve multiple transactions. For example if the first transaction fails and the customer tries a different credit card.
NXT
A: 

Remove the basket items as soon as they ordered and disable the submit button.

In this case even if the user comes back, refresh etc. can't buy twice since there will be nothing in the basket to buy.

dr. evil