I tried to make use of $_SERVER, but it didn't work for me.
What I need is:
In order to access a page on my site, the user must come back from Paypal. If he isn't redirected from Paypal to my site, then don't execute the file but give the user an error instead.
How can I do this?
I tried the following:
$url = 'paypal';
if(strstr($_SERVER['HTTP_REFERER'], $url)) {
// my code
} else {
// my error
}
This didn't work for me, how can I make this work, example link from paypal is (it's pretty long):
https://www.paypal.com/us/cgi-bin/webscr?cmd=_flow&SESSION=39QzTUoR0GugSwdZjeJ5zf4EkFIa2-rlRsdrqxfx4O3ibIMuzY3Eab7y6Dq&dispatch=5885d80a13c0db1f8e263663d3faee8dc60d77e6184470d515cedf52660ea0cd
Please help, this is a security exploit for something I'm working on.
You cannot reliably guarantee that. In general in these scenarios, you could do a server-side check with the payment gateway to see if the transaction id (or whatever is passed back to you) is valid, and that the amount was successfully paid.
You should consider checking out PayPal's Instant Payment Notification service and implement a listener for that. PayPal has some sample code for that in various languages. This is a brief overview of the IPN protocol:
PayPal sends your IPN listener a message that notifies you of the event (a received payment, for example).
Your listener sends the complete unaltered message back to PayPal; the message must contain the same fields in the same order and be encoded in the same way as the original message.
PayPal sends a single word back, which is either VERIFIED if the message originated with PayPal or INVALID if there is any discrepancy with what was originally sent.
Once the IPN is verified, you may then unlock the features/options that your users paid for, as #cHao suggested in the other answer.
Further reading:
PayPal Integration Center: Introducing IPN
Any method of checking what site the user came from can be fudged by the user, whether for exploit reasons (bypassing the "pay for my stuff" part) or for privacy ("It's none of your business what I was just looking at"). Don't rely on it for critical stuff.
You're better off listening for IPN posts from Paypal and using them to unlock features that people have paid for. There might be a bit of a delay, but it's generally really short. Usually by the time a user's bounced back to a "thanks for your order!" page, and clicked a link to access what they bought, the IPN has come through.
Referrers are not reliable. They get blocked or replaced quite often. And the user client can replace them with whatever he wants.
You trust the client which wrong.
You need to get confirmation directly from paypal, or paypal needs to give the user an unforgeable token.
And you need to validate the payment amount too. Else the user can just pay 1 cent.
Honestly, if you think
$url = 'paypal';
if(strstr($_SERVER['HTTP_REFERER'], $url)) {
// my code
} else {
// my error
}
is going to stop a security exploit, I would recommend you pay somebody more experienced to do this for you, because it is likely you also have other holes in your system. Security in payments is very important.
If you still want to do it yourself, read about PayPal IPN here.
Maybe this snippet can help you at http://www.snipplr.com/view/41575/process-paypal-response/ and the request code is available at http://www.snipplr.com/view/41574/paypal-xclick-payment/
Related
I have Integrated Paypal using php. I know there is return url ,that means when payment is received it will return to the url for our website.My Question is if payment is received and due to internet problem it does not return to our web page, how do I know that payment is received from a particular user?
If there is a network issue and PayPal cannot issue the IPN message, then according to their documentation, they will retry 15 times up to 4 days.
The IPN message service does not assume that your listener will receive all IPN messages. Because the Internet is not 100% reliable, IPNs can get lost or be delayed. To address these issues, the IPN message service includes a retry mechanism that re-sends a message at various intervals until your listener acknowledges receipt. An IPN message may be present up to four days after the original was sent. The maximum number of retries is 15.
https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNIntro/
This item below might help. Instant Payment Notification should work, but in the case of a network failure, if the payment reached PayPal but the purchaser did not get back to your site to complete a purchase, then you should still receive an email from PayPal telling you that you have received a payment.
using paypal button - can my webpage tell if paypal transaction was successful or not?
You get a confirmation email with their name and email address - be aware that occasionally this may not be the user's current, most active email address. You can also log in to your PayPal dashboard to see all details as well, of course.
You can look up your payment details from the email and compare them to your own user records in your database. If the email they use for PayPal is not the same as the one they registered on your site with, you can still look up their name from the email - in practice it seems to happen extremely rarely that payments have such a problem in my personal experience
I set up a script which emails my users with a passcode to get to the online product they bought which is emailed to them so they can submit that later along with their email address. This is the first thing that happens on return to my script so at least if the site fails to respond properly they can get to what they bought later.
The script uses PHPMailer and cc's me with their passcode so I have it available to re-send to them if they write with a complaint. It doesn't help if the PayPal return for Instant Payment Notification fails completely but the other answers cover that very fully and detail the PayPal repeat attempt process well.
Instant Payment Notification scripts can be downloaded from PayPal for modification by yourself as per the article linked to above.
To be perfectly honest, this is one of PayPal Standard's largest holes. IPN is a POST callback (as is PDT) and they check to make sure they get a 200 response or else they retry (and you can use the IPN history in your PayPal account to resend missing IPNs). But this method still relies on you getting the callback in a timely manner and it's not foolproof. Worse, you need to verify the IPN call and that introduces yet another point of failure in calling PayPal to make sure they did indeed send you the IPN you got.
There's a couple of ways to deal with this
Audit your account regularly. This is a good idea in general, but for a small website this shouldn't be terribly hard. Match your invoices up to your PayPal payments. Obviously this doesn't scale well so...
Switch to Payments Pro. There's more hurdles to this (like more PCI compliance, SSL certificate, etc) but the major advantage is that the API is far less susceptible to the whims of the Internet and only involves one call for credit cards (you can ignore the IPN because the API tells you everything you need to know). The worst that can happen is you send a payment API call and fail to get a response. This is exceptionally rare as PayPal makes sure their API is 99.9% reliable (IPN relies on your server being reliable). Speaking from experience, Payments Pro has far fewer issues than IPN does.
In your application, you should have a status field for orders. If you haven't received the ipn, you wouldn't change the status to Paid.
After that, if you receive an email from Paypal that someone has paid, check the order number, and change the status manually.
how do I know that payment is received from a particular user?
Paypal will send an email both user and you.
Paypal offers 2 solutions for your problem.
PayPal IPN - it notifies the server with a POST request to a specific URL, whena transaction has been successful, declined, aborted by user and so on. Paypal provide an IPN Simulator (the worst simulator ever) in order to test its functionality. you may give it a try at : https://developer.paypal.com/developer/ipnSimulator/
Paypal WebHooks - The webhooks are the "New Kid in the Block",they are basically "user-defined HTTP callbacks that receive events for the subscribed event types. Webhooks are asynchronous, the order is not guaranteed, and idempotency may lead to the same event being sent more than once." as stated in the Paypal documentation.
You can read more about it on : https://developer.paypal.com/docs/integration/direct/rest-webhooks-overview/
For any further help, comment below and I shall try to help.
Cheers,
You have to use notify_url for this purpose
<input type="hidden" name="notify_url" value="https://domain-name.com/ipn.php">
I need to add payments to a website I'm working on and I'm not sure what to do. On the website, users will be able to purchase virtual points. So once they pay, their account will be credited with x number of points.
I came across this tutorial on IPN http://phprocks.letsnurture.com/paypal-ipn-with-php/ which I used, and was able to do a few tests using the PayPal IPN simulator(https://developer.paypal.com/developer/ipnSimulator). Everything went well and the user's data was saved to the database after the "payment".
However someone suggested another way to handle payments. Using this http://blog.scrobbld.com/paypal/protecting-your-payments-with-ewp/ tutorial which encrypts the payment.
In the second tutorial the author mentions this:
"If they use Firefox, and have installed Firebug, it is more than easy to edit the DOM of the page, and post that off to PayPal instead. So instead of having the amount at 12.99 , I might set it to:"
<input type="hidden" name="amount" value="0.99">
but doesn't this if from the first tutorial take care of this aspect? Or does the encryption from the second tutorial offer more security for the payment?
// 3. Make sure the amount(s) paid match
if ($_POST['mc_gross'] != '0.34')
{
$errmsg .= "'mc_gross' does not match: ";
$errmsg .= $_POST['mc_gross']."\n";
}
So if I understand this right, I can use the ipn listener class from the first tutorial, together with the encrypted payment from the second tutorial?
Within IPN the transaction has already occurred. So if it doesn't match you can send yourself a notification, automatically refund the payment, or handle it however you want.
A secure button, though, whether encrypted or hosted by PayPal (which is how I prefer) would not show the pricing data in the button code at all, so there's no way for anybody to even make a payment without the correct pricing.
So you could use both together, but the logic in the IPN really would be obsolete if you're using secure buttons in the first place.
The key phrase in Andrew's answer is "has already occurred" (IPN).
If you can actually verify the pricing beforehand, aside from opting for encrypting things, you could use Express Checkout where data is handled server side instead of an HTML form that POSTs directly to Paypal as shown in the sample.
This way you can treat IPN more like what it really is - a "messaging" service based on events in the transaction, rather than making it part of the transaction (where you somehow need to invalidate transactions after the fact).
While "invalidating" (credit/refund/cancel) transactions do occur normally, IMHO, it "should" be because of your business rules (instead of some validation issue, like dealing with tampered data).
"If they use Firefox, and have installed Firebug, it is more than easy to edit the DOM of the page..."
Tampering with HTML form data is an inherent risk in all <form /> and all modern browsers have internal tools (Firefox, Chrome, Internet Explorer) to inspect everything it ("client-side") is involved in. That is why validation (both client and server side) are required in any time of web development.
Hth..
I've a problem with Paypal IPN. The callback works very well.
I've a site and anyone can signup for free in my site. Later, the user can upgrade the account and here intervenes paypal.
How can I be sure that the user (A) paid to the transaction_id (0123) ?
Ex.
User (A) -> Click to button (item_number = (0009)) -> redirect to paypal page;
User (?) paid -> Paypal IPN sended and server received data -> [Which user has paid?]
!! This, without the user return to the site !!
Thank You
I'm sorry #Vincenzo Raco, but that is bad advice.
PDT and IPN are essentially the same exact thing except that PDT sends data to your return URL and IPN sends it to a silent listener.
There is no guarantee that users will make it back to your return URL, even if you have Auto Return enabled, so it's never a good idea to handle post-payment processing tasks on the return URL. If your IPN is getting hacked that means you have a problem with your configuration.
All IPN's are verified with PayPal's servers, and if you're using API calls, hosted buttons, encrypted buttons, etc. people can't see the original code, copy it, and make adjustments to pricing, which would be the only potential "hack" that anybody could do. Just make sure not to use basic, standard HTML buttons and that potential problem goes away.
IPN is definitely what you want to use to handle your post-payment processing. You can save your user record or whatever data you're working with in your database prior to sending the user over to PayPal. You can include the record ID of your database in the PayPal payment request (I typically use the invoice parameter for this) and then that will be returned in IPN so that you can pull that data back out of your database or add new related accordingly.
I am integrating PayPal Express Checkout API into a digital goods/services website. I worked out all the technical stuff, but now I have a theoretical question - when the transaction is done and I get a confirmation from PayPal, what is the best way to store that acknowledgement from paypal, and credit my user's account?
The ConfirmPayment() function in the paypal library returns from paypal with an associative array, including a transaction ID, and acknowledgement that I have the user's money in my business account.
So my plan is, store that transaction ID as a unique value in a SQL table, so if the user for example reloads the confirmation page, which would then re-call ConfirmPayment($token), my PHP script won't just credit their account a second time, because the SQL table will return a unique ID error.
How are smart programmers integrating this last payment confirmation into the rest of their application?
THANKS.
I would do it like so:
Keep a full log of all the messages your receive from Paypal. Just the RAW data should be fine. Then beyond that point don't need that much traceability. If anything ever happens you can check the log. This should really never happen, if you need to look at this log a lot to resolve any issues you have a different kind of problem. This is why my suggestion is: don't put too much time into it, but make sure you have traceability (albeit a very crude one).
If the user reloads the confirmation page, Paypal will not send you another message. Keep in mind that you should only accept transactions that Paypal has verified. The user should not be able to validate his own transactions by bypassing Paypal.
I know that with PayPal Pro, the user enters his information on my site and PayPal processes that in the background.
Still, is it possible to have it like with PayPal standard : the user gets redirected to PayPal site, enters his information there, pays there, and come back ?
I'm asking cause my client has PayPal Pro, however I don't feel comfortable with gathering payment data myself. I would prefer PayPal to do that for me.
Short answer: Yes, you can use IPN.
Longer answer:
Either way you want to have an SSL certificate, and to handle various payment information.
If you're using IPN, the user gets redirected to the PayPal site, pays, and gets redirected back, and you receive a notification to one of your scripts. That script will have to check if the data you receive is similar to what you sent, and other checks. You may not receive the notification instantly, sometimes it takes a few days to get it (very rarely though).
With PayPal Pro, the user enters his credit card details and submits them. You will have to make some checks here, but after that you send the info to PayPal, and you receive the response (either success or response) - instantly.
These are the major differences, it's nothing mind boggling one way or the other, you just need to use the API documentation.