Integration guide

If you are new to processing credit card transactions in an interactive manner, there are a number of issues to be aware of. In short, it is very important that you make sure that the transaction gets attempted exactly once and that nothing interrupts this process. The internet and users being what they are suggests that this goal can never be completely achieved. There are steps you can take to make it less likely that you'll hit problems.

To assist in understanding the problems, here is a rough diagram of what happens when the user hits the 'Pay' button on your website:


  1. User clicks "Pay" on your website which sends a request via the internet to Anchor's servers.
  2. Anchor's server sends a request via the internet to the bank.
  3. The bank processes the payment request and figures out whether or not it was successful.
  4. Anchor's servers receive this message and return it to your website's code.
  5. Your code generates a response message and sends that back to the client via the internet.

The problem with this scenario (even though it is considered industry best practice) is that passing 4 messages through the internet and waiting for intermediate computers to do their work will take a significant amount of time. Users tend to react to slow websites by clicking the 'Reload' button, or perhaps by clicking your 'Pay' link again. Others will make sure they hit 'Stop' before trying again. If your user unwittingly (or even wittingly) sends their request to the webserver twice, their payment will be processed again; in other words their card will be charged twice.

The best protection here is prevention; it is unfeasibly difficult to recover from multiple payment errors on anything more than a strictly occasional basis. Here are some suggestions on how you can minimise the risk of double-charging:

  1. Inform the user about what is happening. Tell them that they'll need to wait a little while (say up to 30 seconds) for the payment to be processed. Most users will be accepting of this fact since they will have observed that using the credit-card machine in shops takes a few seconds to do its job.

  2. If possible, consider using offline processing of credit cards. This allows you to return to the user imediately which will give the user confidence in your site and allow you to check for duplicate payments at your leisure.

  3. Ensure that the user can't click "Pay" twice . There are numerous ways to achieve this, but the most common approach currently is to open your payment page in a new window and use Javascript to close the window once "Pay" is clicked. This makes it impossible for your user to re-submit the payment details.

  4. If you don't want new windows popping up from your site (note that newer browsers will block attempts to open new windows), you can ensure that payment data is not used twice by recording the payment data in a database before processing the payment. This will allow you to detect when users re-submit data by inspecting your database.
  5. Ensure that details of the transaction are written to the database as soon as the payment is processed. That will ensure that even if the user doesn't get the webpage they were expecting, the state of the database will be correct so the services should ultimately get provisioned.

In the interests of ensuring that your client has the best possible experience with your site, you should validate the data they provide before sending it off for processing. Informing people that they've mistyped their credit card number will result in more successful transactions than informing them that there was a problem after the fact. The payment gateway library includes a simple function that will check for mistyped credit card numbers using the Luhn algorithm. Note that it does no sanity checking for prefixes and so forth; it is designed to protect against innocent errors rather than malicious ones.

Here is some example code that uses the validator:

  • <?php
    ccardno  = $_POST['cc_number'];
    valid    = valid_ccard($ccardno);
    if ($valid) {
        # allow the card to be processed.
    } else {
        # report an error back to the user and allow them to retry.