Knowledgebase

[PHP] Expire a page and prevent page reload/refresh

Posted by latheesan, 09-11-2007, 03:12 PM
Hello. I am writing a little shop script for electronic goods, using PayPal IPN service. Here's my problem. After user pays for an item, there is a button on the palpal page to return to the site. When they click that, they get taken to to Thanks.php page. At the Thanks.php page, paypal post all data about the transaction to it, so i use it to store it into myssql db. the problem with this is, someone could easily press the F5/refresh site. By doing so, paypal posted data gets stored twice or more (depending on how many times page was reloaded) into the db. How can i expire a page after i recive data from paypal, so when they refresh that thanks.php page, it says "Page expired" like you normally see on the paypal site itself or hotmail.com etc...?

Posted by Bangalore Job Mob, 09-11-2007, 03:51 PM
Why isn't your script smart enough to simply empty the cart after the items have been paid for?

Posted by masfenix, 09-11-2007, 04:03 PM
this also depends on the coding language. I code in asp.net and i have prevented refreshes and clicking "back" in asp.net. i can help you but i cant if its in PHP

Posted by HostSentry, 09-11-2007, 04:19 PM
There is a pretty simple way of handling this in any language. Simply have a file (or a DB if you so prefer) that stores a number value. You can start at 0 if you prefer. In the form that passes information to the server-side script (your PHP script), have a hidden value that contains the value of the file (or DB). Once the script processes the form, change the value. This way when the user reloads, it sends the old number. Check in your script if the numbers match, if they don't... they are reloading the same page.

Posted by masfenix, 09-11-2007, 04:26 PM
your browser cache does not change though. People think thats a good device to implement, but for example you have a signup form. you can only signup ONCE with a unique username. if you signup, and press refresh it will signup again using that name. (I dont know about what would happen if the username field in database is set to unique only).

Posted by HostSentry, 09-11-2007, 04:36 PM
Reloading the page sends the same submitted information again. Thus the server's stored value would be different since it is changed each time the form is processed. Kinda like this: Server has a value of 0 to start with. Form is generated for the user to fill out. The form has a hidden value of "0".The user submits the form.The script processes the form, and changes the value of the number to 215The user reloads the page... and resends the value of "0"The script checks the sent "0" against "215", and determines the page is reloaded.What is wrong with that approach?

Posted by latheesan, 09-11-2007, 06:08 PM
You are missing the point. Im having problem with the Thanks.php page, which gathers all the data paypal sent to it and store it in db. When user refreshes the page, it gets stored in db agin and so forth... Isnt there any method i could use to expire a page? that was the orignal question to begin with... or is it only ASP and other languages are capable of doing this?

Posted by Bangalore Job Mob, 09-11-2007, 06:50 PM
You're missing the point of persistent session data. You don't need to "expire" the page, you need to react appropriately to bogus and duplicate data sets. What happens if I don't use a web browser at all but decide to forge my POST request to your script through curl?

Posted by masfenix, 09-11-2007, 07:06 PM
oh im sorry, i misunderstood you. i took a more complicated root though, with javascript and messing with asp.net engine

Posted by Adam-AEC, 09-11-2007, 07:06 PM
Why not have paypal send them back to an intermediate page that collects the POST data, and then have that page perform the redirect to thanks.php.

Posted by latheesan, 09-11-2007, 08:28 PM
I've considered this fact and made necessary checks to see that the Thanks.php page is loaded inside the index.php and also it is paypal who is posting to the Thanks.php. e.g. the .htaccess denies access to everyone to Thanks.php and only index.php can include it. Thanks.php will only work if its being included by index.php (i hope this is good enough =/ ) I didn't stop there, i also made nessary checks to make sure that what ever that is posted to Thanks.php is sent back to paypal to validate it. Only if paypal sends "VERIFIED" in the ipn-validation, user is awarded what he/she bought. I guess i could do this in one way. Add another field to my transaction log called "session_id" and in my mysql query part, i could check if there are any records in db for the current logged in user and his session id, if yes, ignore the mysql insert. What are the chance of having session_id being same for same user?

Posted by masfenix, 09-11-2007, 09:22 PM
i dont know about mysql, but MSSQL is pretty rare. MS has done a good job on there GUIDs

Posted by latheesan, 09-11-2007, 09:42 PM
While attempting to eliminate double posing in the part that saves transaction data to db, i somehow managed to get this following error: This is my code - http://rafb.net/p/NKmXON84.html Why is this error showing up =? Last edited by latheesan; 09-11-2007 at 09:46 PM.

Posted by brandrocker, 09-11-2007, 11:04 PM
Use sessions to prevent double entry of data. Register a new session var and set it to true initially. Thanks.php will check this session var before entering data in the database. It will enter data only if session var is set to true. Once the script is executed set this to false. Now if user refreshes the page, the script will indicate that action has already been taken. Regarding sprintf() I would place the entire query in a variable: $sqlString and use mysql_query($sqlString); Hope this helps.

Posted by Bangalore Job Mob, 09-12-2007, 01:13 AM
A) If it's not meant to be loaded in a web browser, keep it outside the document root. B) If index.php can include it and index.php can be loaded in a web browser then there'd better be something else at the gate. C) Even if the vagaries of session data management are too complicated for you, how hard is it to query the database and look for an identical transaction ID before doing another insert? Sure it's a performance hit, but I'm guessing you don't have millions of customers buying videogame gold or whatever it is you're selling.

Posted by sandykadam, 09-12-2007, 01:43 AM
Hi, Do one simple thing. Once you get request from paypal with post data then you do your usual coding of updating db. Once you done with db updation just again redirect your page to Thanks.php with some flag. For eg: So flag=1 means you have done with updation of db and no more updation to do even if user has refresh page. By default when page will come from paypal it willbe Thanks.php in address bar so it will go in that condition and update and then redirect so next time if user refresh it will not again update your db coz it will be Thanks.php?flag=1

Posted by Jatinder, 09-12-2007, 02:34 AM
Check your PDT/IPN variables. You should be getting a variable, txn_id, from PayPal. This is a unique transaction ID. Whenever the thanks.php page is called by PDT, just query the database whether a record with this txn_id already exists or not. If, the record exists, do not run the insert query. You do not need to prevent the page from refreshing. Last edited by Jatinder; 09-12-2007 at 02:47 AM.

Posted by latheesan, 09-12-2007, 08:52 AM
Read my previous post, this is exactly what i just did. My problem now is the sprintf() error...

Posted by Bangalore Job Mob, 09-12-2007, 12:49 PM
Read the documentation on sprintf. I don't see any reason for you to be calling it at all since you're just concatenating strings.

Posted by latheesan, 09-12-2007, 10:17 PM
Once i was reading an article about SQL Injection Prevention tricks and the article quoted, the best way to prevent SQL Injection is to use this method, when ever a query is made: I been using this method long as i can remember now =/

Posted by Bangalore Job Mob, 09-13-2007, 12:08 AM
So you don't actually know what sprintf does, you just call it because you saw someone else do it once?

Posted by latheesan, 09-13-2007, 06:27 AM
Well you learn from tutorials and if one suggested that best way to beat SQL Injection is through that method, then why shouldn't you use that implementation?

Posted by Jatinder, 09-13-2007, 07:58 AM
Whoever wrote the tutorial doesn't know what he is talking about. sprintf makes sense only if you pass other parameters along with the format string. Here is an example: Take a look at http://www.php.net/manual/en/function.mysql-query.php to learn how to use sprintf in queries. Also take a look at http://in.php.net/manual/en/function.sprintf.php

Posted by latheesan, 09-13-2007, 10:52 AM
I see, so the sprintf() is not needed when inserting record and mysql_real_escape() is sufficient enough to prevent any possible SQL Injection?

Posted by Jatinder, 09-13-2007, 12:13 PM
sprintf does have its place in DB queries provided that use it correctly. Take a look at http://www.php.net/manual/en/function.mysql-query.php for an example on how to use sprintf properly.

Posted by Bangalore Job Mob, 09-13-2007, 12:37 PM
You're living proof that not everyone who posts some random blob of code on the internet knows what they're talking about.

Posted by latheesan, 09-14-2007, 10:23 PM
Oh wow, im a living proof of something, but you? you're a nobody. Lol just kidding. Im sorry some of us couldn't afford to born into this world with an incredibly large head like yours which matches ur ego. Relax dude, I just came to this board to get some assistance with code and i think its rude of you to call my code "random blob". If i misunderstood something, it would've been alot nicer to just point me in the right direction, instead of giving me satus like "living proof" and criticise my code and provoke me =/

Posted by Bangalore Job Mob, 09-14-2007, 11:01 PM
That's fascinating.

Posted by lpmusic, 09-15-2007, 01:26 AM
Learn Paypal terms, that's not IPN, that's PDT (Payment Data Transfer).

Posted by latheesan, 09-16-2007, 08:26 AM
Yes im aware of it. PDT = when paypal send data back to a specified URL IPN = when i send back the data posted me via PDT back to paypal and paypal replies weather a payment was VERIFIED or not~

Posted by Jatinder, 09-16-2007, 04:05 PM
Well, you haven't got it quite right. PDT => This is the data sent to your Return URL. Please note PDT is meant only to display transaction details to customers. It should no be used to make entries to the database. If a customer closes the browser after a successful payment but before being redirected to your site, your website will never receive the PDT data. IPN => This the data sent asynchronously to your IPN URL. You should use IPN to make any database changes. IPN will always be sent even if the visitor closes the browser. Even if your server is down, PayPal will keep trying to send the IPN.

Posted by latheesan, 09-21-2007, 04:30 PM
Oh i see, im beginning get a clear picture of this now. So, i write a separate php script called IPN_Process.php for e.g. and have this linked to the paypal account. Then this php file will take care of every transaction made. So, while making this script, i thought i could make it secure by puttng this inside a folder called "secure" and a .htaccess with the following: Options -Indexes order allow,deny deny from all order deny,allow deny from all allow from 216.113.188.64 216.113.188.64 is the ip i got from pinging the paypal.com domain. Would this setup work? Prevent all others from accessing/posting data into the IPN_Process.php and only allow paypal do it?

Posted by Jatinder, 09-21-2007, 10:00 PM
The IP might change. I guess PayPal has more than one server to send out IPN. A expected approach would be to verify each IPN with PayPal. PayPal manual describes how to verify IPNs.



Was this answer helpful?

Add to Favourites Add to Favourites

Print this Article Print this Article

Also Read
Advice needed. (Views: 603)


Language:

Client Login

Email

Password

Remember Me

Search