0

I have a complicated setup for a shop situation.

People can buy unique products in a short time frame and pay via PayPal. So I need to be sure the products are not bought multiple times. For that purpose on checkout I am using a custom PHP file that updates the items in the database to a "reserved" status and then sends the form to PayPal via header(). This is all working very nicely.

Because we have limited items to sell and such a limited time frame, I want to make items available again if the buyer aborts the payment process. I do have PDT set up and running but the transaction protocol sometimes comes with extended delay. So ten minutes after the checkout I want to check the database to see if the transaction came through. If the item is really sold (status is changed by the PDT script) all is fine, if it is not sold, I want to reset the reservation status and make the item available for other buyers again.

Here is the setup of my code:

if ($resstatus == "0"){
    $result = mysqli_query($mysqli, "UPDATE `table` SET `Reserved`='1' WHERE `AID`='$AID' AND `itemID`='$itemD1'");
    header('Location: https://www.paypal.com/cgi-bin/webscr?'.$post_string);
    sleep(600); //wait ten minutes before checking DB
    if ($sold == "0"){
        $reset = mysqli_query($mysqli, "UPDATE `table` SET `Reserved`='0' WHERE `AID`='$AID' AND `itemID`='$itemD1'");
    }
}

Everything is executed, but the header redirect is also delayed the time span defined in sleep(). This doesn't make sense to me at all. If it would redirect and NOT execute anything afterwards - that's one thing. But it executes everything but behaves as if the order was first sleep() and then header().

I am going for a different approach now by saving a timestamp on checkout and checking for units with reservation-timestamps older than ten minutes when the shop is loaded. That should work and is probably more elegant.

But I'm still puzzled by the above behavior and would like to know where my error in reasoning is buried.

GrumpyCrouton
  • 8,486
  • 7
  • 32
  • 71
  • 2
    [Little Bobby](http://bobby-tables.com/) says **[you may be at risk for SQL Injection Attacks](https://stackoverflow.com/q/60174/)**. Learn about [Prepared Statements](https://en.wikipedia.org/wiki/Prepared_statement) with [parameterized queries](https://stackoverflow.com/a/4712113/5827005). I recommend `PDO`, which I [wrote a function for](http://paragoncds.com/grumpy/pdoquery/#function) to make it extremely easy, clean, and more secure than using non-parameterized queries. [This may help you choose between `MySQLi` and `PDO`](http://php.net/manual/en/mysqlinfo.api.choosing.php). – GrumpyCrouton Sep 08 '17 at 16:15

1 Answers1

0

It depends on the SAPI you are using. Nevertheless you can not count on the code after sleep to be executed and should really be using a cron job that checks the timestamps and removes the reservations.

Especially since you have such a big timeout the server would probably terminate the long running script. Also, your script while sleeping is also tying one of the processes that could be used for serving other content.

BTW, this would probably work:

ob_start();
header('Location: https://www.paypal.com/cgi-bin/webscr?'.$post_string);
ob_end_flush();
flush();
ob_end_clean();
sleep(600);

See also here

Goran Jurić
  • 1,829
  • 13
  • 17
  • I did it without a cronjob now. Basically I update the database every time someone loads the shop page. Works fine. I was just irritated that everything after header() was being executed but header() itself was delayed. Thanks for taking the time to explain! – berlinaise Sep 08 '17 at 17:26