PayPal - IPN Listener and encrypting payment - 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..

Related

How to capture success on Paypal's Smart Checkout and return a Serial Key?

Introduction
Hello I'm going to sell a software using serial keys. Any person can go into my webpage and click on the paypal button to buy a serial key, they don't need to register.
What I'm trying to achieve
I need to let any person use the button and receive a serial key when the payment is done.
So the workflow would be something like:
Any person (non-registered) clicks on the button.
The paypal page shows up.
The user pays and gets redirected to a page that shows something like "Congratulations, here is your serial key: {{serialKey}}" and also receives the same serialKey via email.
What I tried
I'm trying to use Paypal's Smart Checkout but I don't understand how to implement what I need.
Right now I'm able to:
Render the button.
The button performs a request to my back to get the price (so the user can't change it and trick me).
The paypal page shows up.
On success it performs a request to my back.
On failure it restarts.
What I'm missing:
How can I check that the payment did actually succeed on the back, I mean that I received the money? Is there any way that I can post to paypal using the ID and see if I that transaction was correct?
Additional question
Is this the right approach? All I need is to let anyone click the button, pay and receive a serial key ONLY if the payment was correct. Right now it seems too complex for what I need. I don't understand everything I see on the paypal docs, if you follow it line by line the examples don't work, you have to adapt a lot of the code and I'm not sure about what I'm doing.
I also read IPN's docs but using it I won't be able to redirect the user because everything would be done in the back without the user even knowing what is happening.
Final text
Any help is appreciated. I'm asking here because I saw a lot of another questions about paypal like this one that were upvoted.
The most robust approach is to combine the PayPal Checkout front-end with a v2/orders backend for payment setup and capture.
create order
capture order
This way the capture happens from your server, so you have an immediate success/failure API response -- and can immediately do whatever you need to do to handle the business logic of the digital good purchase (serial key activation/distribution)
Once you have everything working well for the happy path, don't neglect to handle funding source failures, so that if the capture fails due to e.g. the buyer's first card being declined, this is propagated back to the UI and the buyer can select a different funding source.

Is server-side validation necessary for donations using PayPal checkout REST?

I have been following this page in the documentation to create a PayPal checkout integration for the purpose of allowing visitors to a site to make donations: https://developer.paypal.com/docs/checkout/integrate/#6-verify-the-transaction. It seems that the more simple donations buttons cannot be used, as it is a requirement that donations are saved to a database table.
I have so far implemented all of the integration up to some of part 6, which verifies the transaction on the server. The code provided on the page (I am using PHP) is not clear and all of the examples of server side validation that I can find refer to purchases, which do not apply to donations. However, even without this, in sandbox mode the integration appears to work. Would this also work in live mode without server validation (and there is no concern of a third-party editing "prices", as this is a donation, so why not let them pay whatever they like?)? If server validation is necessary, what resources are there that exaplain/demonstrate how to do server-side validation of transactions for simple payments (e.g. donations) that do not involve purchases?
Thank you for reading.
Per your own requirements, you want it to call your server after capture, so that it saves a record of the transaction in your server. Everything else is optional, and as you mention may not be needed for any purpose.

subscr_payment using paypal ipn simulator

The paypal IPN simulator "currently" (As in I'm assuming never will) does not have functionality to test the subscr_payment payment option, this is really putting a dead hault in my project. I've read that I can just create a button that simulates this, but I don't have a clue how and after looking I can't find any information on it.
I'm creating a subscription based system for hosting a special type of website, I have everything done besides for the subscription model now and it seems like it's going to be the hardest part.
It is completely possible to test recurring billing with Paypal.
There are multiple ways possible for this.
One is the paypal subscribe button and another way (which i have used) is via a subscription form.
For the subscribe button you can refer this documentation, it contains all the information you need to setup this.
For second method, you need to create a form and place all the required variable in that form.
All the required variables are listed here.
I hope this helps.
Hopefully this workaround will help you. From within the PayPal developer site, you can go to the IPN simulator, select Transaction Type as Web Accept, click Show All Fields. You can then edit txn_type to be subscr_payment, subscr_signup, etc.
It's not perfect, as it doesn't give you all of the variables, but you can put info in other entries, and use a logical to determine whether or not the correct entry exists.
Do one test subscription, so that you have the values, and then work from there.

If user didn't come from HERE then do not process - How?

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/

How to keep PayPal variables secure

I'm trying to link my 3rd party shopping cart to PayPal, and in the process I'm finding that my variables are extremely exposed, such that, if someone uses, say, Firebug, to manipulate the values of my variables, they can change the cost of the items in the transaction.
I'm very new to online carts and shopping, so my question is how do I keep this layer of exposure away from users and secure for the website?
The answer is in the Instant Payment Notification service.
Upon completing the transaction, PayPal notifies you, in a separate process, of the payment details for the last transaction.
You can check these details against the data you stored locally. If they match, all is fine. If they do not match, you will need to investigate the issue.
Never understood why PayPal does not allow the data to be signed with some sort of hash + shared secret... but that does not help you any further.
If you POST the variables to PayPal, you can encrypt the data. Unfortunately, this is not possible for a GET request, triggered from a redirect.
There is a way of getting PayPal to host the button variables on their side. Look out for PayPal Hosted Buttons in their documentation:
https://cms.paypal.com/uk/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ButtonMgrAPIIntro#id093VD0JE0Y4
Otherwise verify with IPN as mentioned bu Jacco.
Use the PayPal NVP or SOAP API to create an encrypted button. Basically you set all the information using PHP and then the API gives you the HTML.
Alternatively if you only have a couple of products you can make custom buttons.
The API's are well documented and easy to use. Personally I used the NVP as it was recommended for less experienced programmers. You can also use both in with the IPN (Instant Payment Notification) system so that for example digital products can be automatically emailed.

Categories