paypal custom form in php

It's not so hard to do it if you have good example. Unfortunately it was hard for me to find good example. So I describe it here. Here is how I did that:
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
	<input type="hidden" name="cmd" value="_xclick" />
	<input type="hidden" name="amount" value="9.99" /><!-- price -->
	<input type="hidden" name="item_name" value="Some text, name of your product and maybe some ID" /> 
	<input type="hidden" name="currency_code" value="USD" />
	<input type="hidden" name="business" value="peter.s.1208@gmail.com" />
	<input type="hidden" name="return" value="www.peter-sobieraj.com" /><!-- url where to go after paying -->
	<input type="hidden" name="custom" value="some IDs or any text data that you want to remember in order" />
	<input type="submit" value="Pay with PayPal" name="submit" />
</form>
Change amount to your price, and busisness to your email that you use in paypal (or maybe leave my ;), I will love some extra money ).

At that moment it should work, but it's not secure !!!


Form above is in HTML, so with Firebug everybody can edit data before sending it. Now we need to make sure that money come in, and price amount is correct. For that we will need to create file for example listener.php in your sever, and configure our paypal profile so after every translation paypal.com will run our listener. Everybody can run our listener (if they know how we name it). So we need to call paypal.com from our listener to check is it correct for sure sure. Here is a example code from paypal site for listener.php. It tuck me a while before I find it on their page. But it work perfectly.
<?php
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
 
foreach ($_POST as $key => $value) {
	$value = urlencode(stripslashes($value));
	$req .= "&$key=$value";
}
 
// post back to PayPal system to validate
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen('ssl://www.paypal.com', 443, $errno, $errstr, 30);
 
// assign posted variables 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"];
 
if (!$fp) {
	// HTTP ERROR
} else {
	fputs ($fp, $header . $req);
	while (!feof($fp)) {
		$res = fgets ($fp, 1024);
		if (strcmp ($res, "VERIFIED") == 0) {
			///@todo check the payment_status is Completed
			///@todo check that txn_id has not been previously processed
			///@todo check that receiver_email is your Primary PayPal email
			///@todo check that payment_amount/payment_currency are correct
			///@todo save in MySQL or somewhere, or send mail, that payment was Complite.
		}
		else if (strcmp ($res, "INVALID") == 0) {
			// log for manual investigation
		}
	}
	fclose ($fp);
}
?>
If you do only last @todo, then It will work, but it won't be full secure. Save that file on your server. For example let your sever be www.yourDomain.com. Now go to your paypal profile. Go to "My Account" -> "Profile" -> "Instant Payment Notification Preferences" If they move it somewhere search for IPN or "Instant Payment Notification". Now as "Notification URL" enter "http://www.yourDomain.com/listener.php" and enable "Message delivery". That will make paypal call (download) http://www.yourDomain.com/listener.php every time when somebody will pay you. And send detail data in post.

OK. Now it will work and it will be secure.


For test you can use www.sandbox.paypal.com, not www.paypal.com. It's copy of paypal service where every data are fake. It's for testing. Good Luck.