SF23103 Posted July 23, 2016 Share Posted July 23, 2016 Hello, I have a multi page form. On the third and final page, the user submits payment information. Upon form submission, it sends payment information to a payment processor. If it is successful, the form submits all of the form data to my database. It includes a payment successful field in my database, but of course no credit card information is stored - that's all handled on the payment processor site. If the payment is not successful, the page loads errors to the user and the form is not submitted to my database until the payment is successful. I am starting to see an issue where I am receiving duplicate payments. I am assuming that people are clicking the submit button multiple times while the payment is processing, and it's sending multiple authorization requests to the payment processor. The payment processor automatically catches some of these, but not all. My question is to what logic is most appropriate reduce duplicate payments. The solution that came to mind was disabling the submit button upon click, but then re-activating if the payment was declined, so the user could re-submit. Of course, I would rather solve this on the server side with php. Is this best handled with cookies? If so, can someone explain the basic logic on how that would work? Thanks for your help as always. Quote Link to comment https://forums.phpfreaks.com/topic/301556-preventing-duplicate-form-submissions/ Share on other sites More sharing options...
benanamen Posted July 23, 2016 Share Posted July 23, 2016 (edited) PRG - Post/Redirect/Get https://en.wikipedia.org/wiki/Post/Redirect/Get Edited July 23, 2016 by benanamen 1 Quote Link to comment https://forums.phpfreaks.com/topic/301556-preventing-duplicate-form-submissions/#findComment-1534882 Share on other sites More sharing options...
SF23103 Posted July 23, 2016 Author Share Posted July 23, 2016 That makes sense, and I can see how that would prevent refresh and back button resubmission. Does that protect against multiple submit button presses while awaiting the success notification from the payment processor? I think people are pressing submit again during the lag that is occurring while the payment is being processed before they are sent to the thank-you page. Quote Link to comment https://forums.phpfreaks.com/topic/301556-preventing-duplicate-form-submissions/#findComment-1534884 Share on other sites More sharing options...
Zane Posted July 23, 2016 Share Posted July 23, 2016 You could set a session/cookie variable value with a boolean. Like, iniitated_payment. Set to true on click of successful submission (no form errors) and only allow logic to occur when that cookie's value is false. If your payment engine throws an error, then set it back the cookie back to false... or whatever. Several things you could do; it's your UX. Quote Link to comment https://forums.phpfreaks.com/topic/301556-preventing-duplicate-form-submissions/#findComment-1534888 Share on other sites More sharing options...
Jacques1 Posted July 23, 2016 Share Posted July 23, 2016 Any serious transaction must involve a unique transaction ID or nonce. Client-side techniques like disabled buttons, cookies etc. may be sufficient for unimportant actions, but they are by no means reliable. When actual money is involved, you must implement a server-side mechanism which is technically guaranteed to only accept a single submission. What exactly is this payment processor? A professional service? Then it should already have transaction IDs. Quote Link to comment https://forums.phpfreaks.com/topic/301556-preventing-duplicate-form-submissions/#findComment-1534890 Share on other sites More sharing options...
Destramic Posted July 23, 2016 Share Posted July 23, 2016 well i've learned something here had a read and this seems to do the trick on duplicate posts, unless i missed something <?php session_start(); if (isset($_SESSION['form'])) { print_r($_SESSION); print_r($_POST); // use data unset($_SESSION['form']); } else if (isset($_POST['submit'])) { $_SESSION['form'] = $_POST; header("Location: " . $_SERVER['REQUEST_URI']); exit; } else { ?> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>Demo</title> </head> <body> <h1>The Form</h1> <form action="" method="POST"> Some Data: <input type="text" value="some data" name="data" id="data" /><br /> <input name='submit' type="submit" /> </form> </body> </html> <?php } ?> Quote Link to comment https://forums.phpfreaks.com/topic/301556-preventing-duplicate-form-submissions/#findComment-1534923 Share on other sites More sharing options...
Jacques1 Posted July 24, 2016 Share Posted July 24, 2016 This is about a transaction to an external site, not a simple POST request within the application. And as I already said, anything that involves money falls into a different category than normal operations. Relying on (session) cookies is perfectly fine if the goal is to, say, prevent duplicate blog posts. If it fails, there isn't really any damage. But if the user ends up with duplicate payment transactions, that is a problem which must be prevented at all cost. Quote Link to comment https://forums.phpfreaks.com/topic/301556-preventing-duplicate-form-submissions/#findComment-1534931 Share on other sites More sharing options...
SF23103 Posted July 26, 2016 Author Share Posted July 26, 2016 Any serious transaction must involve a unique transaction ID or nonce. Client-side techniques like disabled buttons, cookies etc. may be sufficient for unimportant actions, but they are by no means reliable. When actual money is involved, you must implement a server-side mechanism which is technically guaranteed to only accept a single submission. What exactly is this payment processor? A professional service? Then it should already have transaction IDs. I'm using Braintree, but I must be doing something wrong with the unique transaction ID/nonce. In looking at the code, it seems to post the transaction_id after success. if($_POST['month']) { $result = Braintree_Transaction::sale(array( "amount" => $fields[total_cost] . ".00", "creditCard" => array( "number" => $_POST["number"], "cvv" => $_POST["cvv"], "expirationMonth" => $_POST["month"], "expirationYear" => $_POST["year"], "cardholderName" => $_POST['first_name'] . " " . $_POST['last_name'], ), "customer" => array( "firstName" => $_POST['first_name'], "lastName" => $_POST['last_name'], "email" => $_POST["billing_email"], ), 'customFields' => array( "class_name" => $fields[class_drop_down], "token" => $fields[token], ), 'billing' => array( "postalCode" => $_POST["billing_zip"], ), )); if ($result->success) { $_POST['transaction_id'] = $result->transaction->id; $params = array( "submit_button" => "submit", "form_data" => $_POST, "no_sessions_url" => "registration.php", "next_page" => "registration-page4.php", "finalize" => true, ); ft_api_process_form($params); $passing_transaction_identification = ($result->transaction->id); } else { $declined_error = "TRUE"; foreach (($result->errors->deepAll()) as $error) { $braintreeError[] = $error->message; } } } Quote Link to comment https://forums.phpfreaks.com/topic/301556-preventing-duplicate-form-submissions/#findComment-1535088 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.