I have a form that processes a payment, but approximately one in every 300 payments comes though twice, my logs show that there were two requests for all these occurrences.
I implemented some JavaScript that disables the submit button after it's clicked, and it seems to work fine for me, but I'm still getting double submissions every now and then.
Does anyone know anything else that could be causing the form to be submitted twice?
As Dagon says, server-side checks are your friend here. Give each instance of the form a randomly generated key (guid would be nice), and store that in the database. Don't accept forms that contain a key that already exists in the db.
Also, are you simply displaying HTML after your form processing logic executes? If so, try redirecting after you process the form.
It is a way: after user presses form submit button, disable it with javascript. That should prevent user from double submitting the form accidently. It works for all sites we implement it like because. Because sometimes user gets impatient and clicks form submit button several times, thats why you get double requests. What you need to make sure it works for all the browsers (disabling the button I mean).
Also you could do it on server side, it just is harder.
We use similar to the upvoted answer in Enable/disable submit button with jQuery and Coldfusion server code
Related
I'm talking about a php form such as the one seen here:
Say I typed my name and ticked one of the checkboxes, but DID NOT yet click submit. Is there any chance the website operator can see what I've written (or even that I've simply entered text), or that I've ticked one of the boxes?
Of course once I click submit, I'm sending a request to the server and they can see what I've submitted. But before I ever click submit, is there any chance they can somehow see my activity?
If the page you are on uses some special technology (e.g. ajax) to send everything you type to the server, then yes. Otherwise, the default is a definite no. I've never heard of anybody logging this, but I guess it can never be guaranteed.
No, not if you only use PHP in combination with HTML.
However, as soon as you involve JavaScript, there are definitely ways to send this information to the server. For example have a look into Ajax.
First, I realize that there are other questions asked that are similar to this one, but they do not contain any definitive solutions to my problem.
When a customer submits an order, I need to be able to properly prevent my processing script from running more than once for that particular order.
/payment - the customer fills in all of their details and submits the order
/process_order - collects all of the data and processes the order.
What is happening is that my orders are being processed partially and then processed again fully ... and I can only assume that this is because customers are either double-clicking on the submit button, or are clicking the submit button a second time because the process hasn't completed and the browser hasn't redirected to the 'thank you' page yet...
I could just use jQuery to disable the button upon the first click event, but I'd also like to know what I could do on the server side of things to prevent this from happening.
One possible solution is to create, essentially, a nonce token for your form and store it in the session when showing the form.
$_SESSION['formNonce'] = md5( time() . uniquid() );
When generating the form, add it as a hidden field:
<input type="hidden" name="formNonce" value="<?php echo($_SESSION['formNonce']); ?>">
And then when processing it, the first thing you do is validate the nonce is in the session and then remove it. In this way, a second submission won't pass the validation because the nonce token has been removed.
There would be some tweaking and error checking to all of this, but coupled with the javascript button disabling could be a viable solution.
For example, you can use "anti-forgery tockens" approach. Once user does visit a page, there is a tocken assigned. First attempts to submit the page will remove the tocken from valid list so further attempts would fail.
I have a PHP form script which uses mail function. basically you write your email and the email to want to send the recommendation on the page to, and click send.
Here is the problem, once you have sent the recommendation, you can send it again, this time by refreshing the same page!
How can I make script to not remember the previous entered information by same user? flush() or something else. The script is placed in the middle of the page so I don't want the page stop executing after this php form.
Edit:
Thank you guys for your answeres, is there any script so I can use for for storing/validating IPs with help of mysql? or just a "plain text database"?
This is the web browser, not the form, that's causing this behaviour - when you refresh a page that was the result of a form submission, most browsers will offer to resubmit the data.
The usual "fix" is to submit the data to an intermediate page, then redirect the person back to the page they were viewing - that way they'd have to go back one page as well as refresh AND clicking "yes, I want to resubmit the data".
For completeness, consider only allowing a particular ip to use the "send to friend" function once per x seconds/minutes by tracking an IP's last use in a database.
For extra thoroughness, prevent a given recipient being told about a page more than once a day, or something.
Two different things you might experience:
The fact that when you go to your form the information entered previously is remebered. That is typically a function of the webbrowser (and/or the plugings installed) and not so much a problem of your script/form. That is a similar function to how your browser might remeber login credentials for you.
Typically that is not much of an issue, but you could prevent that by generating unique names for your input fields each time the form is loaded.
<input type=text name=email lenght=40>...
then becomes
<inut type=hidden uniqueID=$something>
<input type=text name=email-$something lenght=40>...
and then use the uniqueID in your form processor to reconstruct all other field names when processing the form.
Your second problem is simply that your form processor allows the same content to be processed twice or more. A common problem with common fixes.
A traditional strategy was to redirect the browser to a succes/error page after processing the form contents, which can be reloaded without any penalty. form --> formhandler page (PHP) processes form contents and sends http redirect --> success/error page.
Or more common nowadays, store the above uniqueID of the form (e.g. in a database) and refuse to process a second time.
So I have a 2 page registration page where on the first page the user inputs all his/her data and then clicks continue. On the 2nd page, they choose certain options and then click continue there, this will then take them somewhere else where their payments can be handled (not related to me at all).
I also have a Insert.php file that simply inserts all the user's data into the database. When clicking submit on page2, it actually redirects them to Insert.php, which inserts and then redirects them to the external payment page. I had to do this because for some reason the ajax call just wouldn't work.
My question is, what if right after they click submit on the 2nd page, their computer crashes or they close the browser? Will mysql understand that the connection has been terminated and not save anything or will it save partial data (as much as it could before the user crashed), and if so how do I delete the partial data?
At this point I'm just trying to do as much error handling as I can to prevent any serious problems down the road.
When they click submit, if the browser sends all the post fields, the code you have will happily carry on executing. As far as the server is concerned, nothing of any importance happened.
I would suggest having some post/get checking in the code (as always) which will make sure that all the data has been passed. If it has, it will save properly for the user.
Edit: If you are worried about only some elements of the form being sent before a crash, you can do something like this:
if(!empty($_POST['someElement']) && !empty($_POST['someElement2']) && !empty($_POST['someElement2']))
{
//All your elements are fully submitted, you can save the data safely
}
What is the best way to stop a form from being reprocessed when a user hits a Back button?
I'm following the Post/Redirect/Get pattern, so I don't have a problem if F5 is pushed, but the back button still provides the opportunity to resubmit the form. If this form is a credit card processing page, this is bad.
This question has been asked somewhat here, but the phrasing and answers were of poor quality and not specific to this problem exactly.
I have form.php which submits to itself. If there were no errors in input data upon submission, the user is redirected to form_thanks.php. Hitting back (and "Send" or "Resubmit") once resubmits form.php (BAD!) and then brings them back to form_thanks.php.
Please also include solutions that do not involve using Sessions, if possible.
I would do it a different way. Put up a hidden input with a random string as the value, and when it's submitted store that random string in a session. Set up a simple check to see if they've already posted it and if they have don't accept the input.
This should be done with a single-use token, or a nonce. The php/server should include this token in a hidden form field.
It should store a list of all the recent tokens and each time a form is submitted, it should check to see if the token is in the list of recent valid tokens.
If it's not in the list, then don't reprocess the form.
If it is in the list, then process the form and remove the token from the list.
The tokens can be handled within sessions or just a simple database table without sessions. The tokens should be user-specific though.
This is also the recommended way to avoid CSRF attacks.
Just thinking out loud here. But what about a variation on post/redirect/get where the final get is not actually the final get ;) But rather, it in turn always automatically forwards to the truly final page, so that should the user hit the back button, they return right back whence they came?
EDIT:
Ok, taking into consideration the OP's comment, here's another idea. The URL for the form submission could be made to require a parameter that is good for only one use. That token would be generated (using MD5 or some such) before the form was submitted and could be stored in a database (in response to somebody else's suggestion you requested a solution without using sessions). After the form is processed, this token would then be flagged in the database as having already been used. So that when the page is returned to with the same token, steps can be taken to prevent the resubmission of the form data to the backend.
Late answer, but one could avoid the processing altogether by using an AJAX-based solution; there wouldn't be an issue with including a nonce with this processing scheme, but by using an asynchronous query which, on success, redirects the user, the requests are not repeated by refreshing, pressing back, or anything other than clicking the button.
It is also easy to implement a mechanism that prevents the button from either being pressed twice or being "locked up" if something happened during the request by embedding into the handler for the request (whether high level with PrototypeJS or jQuery or low level with your handrolled function) the mechanisms to enable and disable the button when the request completes and first fires, respectively.
I find that back will bring the form to the state it was before the page was redirected, if that is the case, have a hidden input/variable or something which starts with value say true, then once the form is submitted, and if the value is true, change it to false and then submit, else return false
Try this :
<SCRIPT type="text/javascript">
window.history.forward();
</SCRIPT>