Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 422
  • Last Modified:

Blocking repeat executions of a BUY script

I have a pay_form script where people fill in their credit card information and hit BUY. The BUY script processes the card and send the customer to a Thank You page. If they hit the Back button there they go back to the top of the BUY script and their credit card gets hit again. I'd like to put some kind of a PHP test at the top of the BUY script that senses whether the page is being called from the pay_form - the normal case - or is a return from the Thank You page - where it will cause a double charge.

I tried looking at $_SERVER['HTTP_REFERER'] but this shows the pay_form for both cases.

I'm wondering how people usually solve this.

Thanks for any ideas.

Steve
0
steva
Asked:
steva
  • 2
  • 2
  • 2
  • +2
4 Solutions
 
Cornelia YoderArtistCommented:
Try setting a SESSION variable on the Thank you page and check it on the pay page.

http://php.net/manual/en/features.sessions.php
0
 
Hugh McCurdyCommented:
I would find it useful to have more information about the problem.  

Is the purchase of a single item (perhaps always the same item such as a subscription)?

Or do you use some sort of shopping cart?

Or something else.

Different solutions in my head depending on the nature of the merchandise.
0
 
Cornelia YoderArtistCommented:
hmccurdy, I don't think the nature of the merchandise is an issue.  The problem is common ... when you use the browser Back button, the page you return to is loaded again, and if it is a form submission, the form is submitted again.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
stevaAuthor Commented:
hmcurdy,

Thanks for joining in.  I actually thought yodercm's solution was pretty good and would work but I'm open to all thoughts.

There's no shopping cart.  People select different versions of a single product.  When they hit BUY the script they land on (the BUY script) calculates the price for what they've selected and runs the card. If successful they go to a "Thank You" page.  If they hit the back button on the Thank You page they return to the pay_form page and their card gets run again.  

Another flavor of the problem is that after a successful transaction they can be sent off to a sister site, instead of the Thank You page,  where they've been enrolled as a member with a password and username as a reward for their purchase. If they hit back from  this new site page they return to the pay_form page and the card gets run again.  

It seems that if I set a Session variable "transaction_processed" as soon the the card goes through, and then look  for it at the top of the pay_form script I can avoid running the card more than once for both these scenarios.
0
 
Hugh McCurdyCommented:
yodercm, I said that I'd find it more useful.  Here's my view --

If a shopping cart was used, submit could clear the cart.

If the person was purchasing a subscription, say to access the site, then simply look for a duplicate for the same customer.  One person wouldn't intentionally buy two concurrent subscriptions to access the same web site.

Having said all that, I think the session variable is good but I see two potential problems.
1. The customer actually wants to make 2 distinct purchases during the same browser session.  (Perhaps with different ship to addresses.)
2. Instead of back, user gets tired of page to load, stops the process (or so he thinks) and resubmits.  I don't know if that's actually a problem but I've seen several sites that warn "don't press the submit button twice."

My idea is a bit more complicated and could be a problem on a busy site.  You have the orders (at least the recent ones).  Could you compare the order just submitted to other orders for the same customer?

One more concern.  By the time the user is making a purchase, are you confident that cookies are enabled?
0
 
Dave BaldwinFixer of ProblemsCommented:
Use an intermediate PHP page to process the order that does a 'header' redirect to the Thank You page.  Since the intermediate PHP page is never seen by the browser, the 'back' button can not resubmit the order.  This is a common method.
0
 
Ray PaseurCommented:
Here is how I do it.

<?php // RAY_multi_submit.php
error_reporting(E_ALL);


// PREVENT MULTIPLE SUBMISSIONS DUE TO REPEATED REFRESH, CLICKS ON SUBMIT BUTTON, OR FIRING THE BACK BUTTON
// EXAMPLE:
//    if ( multi_submit() )
//    {
//       handle error
//    }
//    else
//    {
//       normal processing
//    }


// ALWAYS START THE PHP SESSION ON EVERY PAGE
session_start();



// A FUNCTION TO RETURN TRUE OR FALSE ABOUT MULTI-SUBMIT CONDITIONS
function multi_submit($type="POST")
{
    // MAKE THE FUNCTION WORK FOR EITHER GET OR POST SUBMITS
    $input_array = (strtoupper($type) == "GET") ? $_GET : $_POST;

    // GATHER THE CONTENTS OF ALL THE SUBMITTED FIELDS AND MAKE A MESSAGE DIGEST
    $string = NULL;
    foreach ($input_array as $val)
    {
        // CONCATENATE ALL SUBMITTED VALUES
        $string .= $val;
    }
    $string = md5($string);

    // IF THE SESSION VARIABLE IS NOT SET THIS IS NOT A MULTI-SUBMIT
    if (!isset($_SESSION["_multi_submit"]))
    {
        // SAVE THE SUBMITTED DATA MESSAGE DIGEST
        $_SESSION['_multi_submit'] = $string;
        return FALSE;
    }

    // IF THE SESSION DATA MATCHES THE MESSAGE DIGEST THIS IS A MULTI-SUBMIT
    if ($_SESSION['_multi_submit'] === $string)
    {
        return TRUE;
    }
    else
    {
        // SAVE THE MESSAGE DIGEST TO DETECT FUTURE MULTI-SUBMIT
        $_SESSION['_multi_submit'] = $string;
        return FALSE;
    }
}



// SHOW HOW THIS IS DONE
if (!empty($_POST))
{
    if (multi_submit())
    {
        die("ALREADY GOT THAT");
    }
}



// CREATE THE FORM FOR THE DEMONSTRATION
$form = <<<FORM
<form method="post">
ENTER SOMETHING, THEN REENTER IT
<input name="foo" />
<input type="submit">
</form>
FORM;

echo $form;

Open in new window

HTH, ~Ray
0
 
stevaAuthor Commented:
It looks like the best solution is to put a reminder of some kind in $_SESSION to remember that a transaction occurred. If multiple transactions are possible per session the "reminder" needs to more than a boolean.  Ok.  I can craft a solution based on that.

Dave -

Keeping the payment page away from the browser with a header jump seems reasonable but the site is already built and re-architecting the flow at this point is not something I want to get into.  But I'll keep the idea in mind for the next site I do.

I split the points.  Thanks
Steve
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 2
  • 2
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now