Page 2 of 6

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 6:14 am
by Celauran
It doesn't. I was commenting on the flow described in the article you linked, which is about authenticating users and has nothing to do with payments themselves. If you can't use PayPal's IPN, then you'd want to use their Button API.

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 6:17 am
by simonmlewis
OMG there are about 30-40 links on that page and I haven't a clue which to use, or what they do.

I simply want the buyer to click a Buy Now button, and that take them to pay the seller his money via PayPal.

I need the price etc all to be hidden away.

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 6:20 am
by Celauran
I mentioned the Button API and the link had an anchor to that section on the page. There are a number of methods you may need, though BMCreateButton is a given.

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 6:24 am
by simonmlewis
I guess I must be dumb then.
I've gone thru that page, but it's just field titles.
I don't know what the full 'basic' code is, nor do I see how the price from our database "$row->price" is hidden. the Seller won't be adding a button to their account, and then putting that code on our site. They are just uploading the product and entering the price they want.

So I'm still stuck as to how that simple process, become a PayPal API Button that somehow passes the users to pay the seller the price they ask.

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 12:04 pm
by Eric!
I'll try to walk you through it. If you are using the Classic API with simple Buy Now buttons, then try these instructions.

Generate the button dynamically with the seller's email, item description, price, etc. This example button is using the test sandbox so you can test your paypal setup and IPN code.

Code: Select all

<form action='https://www.sandbox.paypal.com/cgi-bin/webscr' method='post'>
<input type='hidden' name='business' value='seller_email@email.com ' />
<input type='hidden' name='notify_url' value='http://YOURDOMAIN/paypal_ipn/process.php' />
<input type='hidden' name='currency_code' value='USD' />
<input type='hidden' name='lc' value='US' />
<input type='hidden' name='item_name' value='Subscription' />
<input type='hidden' name='amount' value='$15.00' />
<input type='hidden' name='sandbox' value='1' />
<input type='hidden' name='type' value='paynow' />
<input type='hidden' name='class' value='signup' />
<input type='hidden' name='custom' value='64b1add1e6349e3a2900fd4a9cf90e1f9e9090c54a983fdd56a3978812e66115' />
<input type='hidden' name='return_url' value='/Purchases' />
<input type='hidden' name='item_number' value='24adf829-15e6-11e3-b5bd-e0cb4e1c48db' />
<input type='hidden' name='cmd' value='_xclick' />
<input  type="submit" value="Buy Now"/>
</form>
This will make a button. Something to note is the 'custom' value. This is how you identify who made the purchase. As I mentioned in my previous message, this value is a unique identifier generated dynamically and specifically for the logged in user. You will need this so that when the purchase information comes back from PayPal to your IPN listener, your server will be able to identify the buyer and reject attempts to spoof your system.

The next step is to build your IPN listener that processes sales. Note that this line from the button form tells paypal where to send the payment notifications:

Code: Select all

<input type='hidden' name='notify_url' value='http://YOURDOMAIN/paypal_ipn/process.php' />
You can find several IPN listener examples on the web and build from there to verify your 'custom' key and credit the correct buyer and seller. Your IPN code also needs to verify in the database that the seller, buyer, item number, price, quantity, etc. all match the incoming PayPal IPN data.

By the way the link you were asking about in regards to API permissions is only necessary when using the PayPal Pro Account's features like ExpressCheckout or DirectPay. You can do the simple one-time Buy Now buttons for PayPal Standard Account's features as I've outlined above.

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 12:45 pm
by simonmlewis
Hi Eric.
Thank you so much for detailing all this.
A few questions for you:
How does this prevent the spammer from copying this code and changing the price to $0.01, and still pass thru via their own HTML to get the $50 item for $0.01?

I don't know what an IPN listener is, but I Assume this is code I have to put into process.php for it to work?
I do hope PayPal's information about this isn't all 'mumbo jumbo' as that just makes zero sense to me.

What you have given above is very similar to the code I entered. But I have a feeling that the process.php talks to my DB. And somehow this is fed back from PayPAl to me, to say the user paid x and the DB says x - do they match?

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 1:10 pm
by Eric!
It doesn't stop anyone from manipulating the form. You protect yourself in the backend with the IPN listener. When paypal sends the IPN notice, it will tell you XYZ payment is for $0.01 for item XXXXX. Then your code looks in the database and finds item XXXXX is really $103.30, so you ignore the spoofed data. (also check the quantity, taxes, whatever you need to verify).

If you read the link I posted it walks you through how the button posts the data to paypal, the user makes the payment. Paypal sends data to your IPN listener (yes this has PHP code and talks to your database). Your listener will repost it back to PayPal to make sure this data was really sent from Paypal and that it is correct. If PayPal says it is verified, then you can start to compare the data to your database, matching prices, items, buyer, seller, etc.

You can also generate encrypted buttons which hides all the data, but this is more complex than you probably need. Here's a stackexchange example http://stackoverflow.com/questions/4106 ... encryption

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 1:15 pm
by simonmlewis
Ok, so it's the listener part that I am probably going to have the hardest job with, and got to read up on.
Most of what PayPal state on their "help" pages, don't normally help me at all. What you have just explained, does make more sense to me. tho how it reads back and forth, I'm unsure. I'm assuming Ajax or some form of "non posting" query happens here too.

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 1:24 pm
by Eric!
No. These are all done using standard POST html methods. The IPN is asynchronous which is why you need the custom field to identify which of your users made the purchase. You can get IPN notices at any point in time. There are certain payment types like echecks that take many days to clear. So you could have a user make a purchase but not get credited for it until several days later after the echeck clears. Your IPN listener will get a pending notice shortly after the purchase, followed by the completed payment notice several days later.

Some times the IPN server goes down and it might be hours before queued payments get sent to your IPN listener.

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 1:26 pm
by simonmlewis
I've just been reading about the IPN. Is this just the page that PayPal takes the user back to on completion of the transaction?
Or is it something that's running "during" the transaction?
As it looks like (just thinking out loud here) that token is stored somehow (like in a session at my end), so if the buyers spoofs the amount to 0.01p, it goes thru paypal, money is TAKEN, but when it comes back to the IPN URL, such as domain.com/purchase&payment=y, the key is checked to ensure it is the same one, the ID of the product was in a session anyway, and that they double checks (somehow) the price PAID is the price on my DB.

How do I know the price they PAID?

Or have I got it completely wrong?

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 1:36 pm
by Eric!
The IPN data is a big list of data that paypal sends directly to your IPN listener. The users never see this. It is strictly their server talking directly to yours.

The IPN data that paypal sends to your site has the amount they paid. First step is to resend all this data back to paypal for them to verify it is from them and it is correct. You have to then compare this to your database. Your seller will get $0.01 in real life, but your site should detect this was fraudulent, notify the admin and perhaps ban the user.

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 1:40 pm
by simonmlewis
I just wrote this and hosted it.
Did the Try Simulator thing, but got the message:
We're sorry, we could not send an IPN.
Maybe I have to change the code they give you, or I am missing fields? I left the Simulator at the default settings.
<?php

// Send an empty HTTP 200 OK response to acknowledge receipt of the notification
header('HTTP/1.1 200 OK');

// Assign payment notification values to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];

// Build the required acknowledgement message out of the notification just received
$req = 'cmd=_notify-validate'; // Add 'cmd=_notify-validate' to beginning of the acknowledgement

foreach ($_POST as $key => $value) { // Loop through the notification NV pairs
$value = urlencode(stripslashes($value)); // Encode these values
$req .= "&$key=$value"; // Add the NV pairs to the acknowledgement
}

// Set up the acknowledgement request headers
$header = "POST /cgi-bin/webscr HTTP/1.1\r\n"; // HTTP POST request
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

// Open a socket for the acknowledgement request
$fp = fsockopen('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);

// Send the HTTP POST request back to PayPal for validation
fputs($fp, $header . $req);

while (!feof($fp)) { // While not EOF
$res = fgets($fp, 1024); // Get the acknowledgement response
if (strcmp ($res, "VERIFIED") == 0) { // Response contains VERIFIED - process notification

// Send an email announcing the IPN message is VERIFIED
$mail_From = "noreply@site.co.uk";
$mail_To = "myemail";
$mail_Subject = "VERIFIED IPN";
$mail_Body = $req;
mail($mail_To, $mail_Subject, $mail_Body, $mail_From);

// Authentication protocol is complete - OK to process notification contents

// Possible processing steps for a payment include the following:

// Check that the payment_status is Completed
// Check that txn_id has not been previously processed
// Check that receiver_email is your Primary PayPal email
// Check that payment_amount/payment_currency are correct
// Process payment

}
else if (strcmp ($res, "INVALID") == 0) { Response contains INVALID - reject notification

// Authentication protocol is complete - begin error handling

// Send an email announcing the IPN message is INVALID
$mail_From = "noreply@site.co.uk";
$mail_To = "myemail";
$mail_Subject = "INVALID IPN";
$mail_Body = $req;

mail($mail_To, $mail_Subject, $mail_Body, $mail_From);
}
}

fclose($fp); // Close the file

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 1:42 pm
by simonmlewis
I know my code here doesn't query any database, but I assumed their test thing would just test the connection at least works.

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 1:46 pm
by Eric!
This probably means it couldn't find your listener on your live server. URL correct? Also you can't run the listener on your localhost you have to use a location that can be publicly accessed.

Re: PayPal buttons: how do I protect sellers' sales?

Posted: Wed Nov 20, 2013 1:51 pm
by simonmlewis
It's definitely there on the live server. And I even copy/pasted the URL from the browser. Incidentially, the URL on the browser shows an empty page. I assumed it might say something, even tho it's just a listener. Anyhow, it's all corrent, but not finding anything.
Does it have to have permissions set special??