It's actually not that complicated, just a bit roundabout. Basically, you create a form which will post information to PayPal to allow the user to pay. Here's some sample code taken from one of my sites (NOTE: it uses variables assumed to exist from my personal implementation, but they're fairly well named):
PHP Code:
<form method="post" action="'.$paypal_send_url.'" autocomplete="off" style="margin:0px;padding:0px;float:left;margin-left:10px;"> <input type="hidden" name="cmd" value="_cart" /> <input type="hidden" name="upload" value="1" /> <input type="hidden" name="no_shipping" value="1" /> <input type="hidden" name="return" value="'.$paypal_return_url.'" /> <input type="hidden" name="invoice" value="'.$an_invoice['purchase_id'].'" /> <input type="hidden" name="business" value="'.$paypal_email.'" /> <input type="hidden" name="item_number_1" value="'.$an_invoice['purchase_id'].'" /> <input type="hidden" name="item_name_1" value="Invoice #'.$an_invoice['purchase_id'].'" /> <input type="hidden" name="amount_1" value="'.$invoice_total.'" /> <input type="image" alt="Pay via PayPal" src="https://www.paypal.com/en_US/i/btn/x-click-but03.gif" /> </form>
Then, when the payment is completed, PayPal will contact your IPN URL and POST data to you which you can then read and validate. Here's an excerpt of some validation code I use:
PHP Code:
<?php require_once('sales_db_connect.php'); //To connect to your database. class paypalIPN_PHP5 { /* Generic class which validates the $_POST data. Meant to be extended to process transactions
Note: For data sanitization, this routine uses mysql_real_escape_string which requires a db connection. */ public $verified = false; public $payment_email_address; public $paypal_url = 'https://www.paypal.com/cgi-bin/webscr'; public $valid_recipient = false; public $db_sanitized_fields; public $paypal_result = '';
function __construct($payment_address, $sandbox=false) { if ($sandbox) { $this->paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; } $this->payment_email_address = strtolower($payment_address);
// Validate data $post_data = ""; foreach ($_POST as $i=>$v) { $post_data .= $i."=".urlencode(stripslashes($v))."&"; $this->db_sanitized_fields[$i] = mysql_real_escape_string(stripslashes($v)); //Sanitize for later use by class extensions } $post_data .= "cmd=_notify-validate"; $ch = curl_init(); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); curl_setopt($ch,CURLOPT_URL,$this->paypal_url); curl_setopt($ch,CURLOPT_POST,1); curl_setopt($ch,CURLOPT_POSTFIELDS,$post_data);
//Start ob to prevent curl_exec from displaying stuff. ob_start();
curl_exec($ch);
//Get contents of output buffer $result=ob_get_contents();
curl_close($ch);
//End ob and erase contents ob_end_clean(); if ($result == "VERIFIED" || $_GET['status'] == 'mark_paid'|| $_GET['status'] == 'void') { $this->verified = true; } else { $this->verified = false; $this->paypal_result = $result;} if ((strtolower($_POST['receiver_email']) == strtolower($this->payment_email_address ) && $_POST['payment_status'] == "Completed")|| $_GET['status'] == 'mark_paid' || $_GET['status'] == 'void' || $_POST['payment_status'] != "Completed") { $this->valid_recipient = true;} else { $this->valid_recipient = false; }
} }
class PayPalIPN extends paypalIPN_PHP5 { function __construct($payment_address, $sandbox=false) { parent::__construct($payment_address, $sandbox); //PHP will not call the parent constructor, so call it explicitly }
function processIPN($override = false) { if ($valid_transaction_number) { //Something you'll need to determine based on your system. //Add log entry $new_status = ''; $brief_description = ''; if ($_POST['payment_status'] == "Reversed") { $new_status = "Chargeback"; $brief_description = 'Chargeback notice received. We will process this immediately.'; } elseif ($_POST['payment_status'] == "Denied" || $_POST['payment_status'] == "Refunded") { $new_status = "Refunded"; $brief_description = 'We have refunded your payment.'; } elseif ($_POST['payment_status'] == "Failed" || $_POST['payment_status'] == "Voided") { $new_status = "Voided"; if ($_GET['status'] == 'void') { $brief_description = 'Invoice voided by admin.'; } else { $brief_description = 'The transaction did not clear with PayPal and PayPal has reported that it will not clear.'; } } elseif ($_POST['txn_type'] == "eot") { $new_status = "Completed"; $brief_description = 'PayPal has reported that the installment plan is completed.'; } elseif ($_POST['txn_type'] == "subscr_cancel") { $new_status = "Refund"; $brief_description = 'Your payment plan has been cancelled.'; } elseif ($_POST['txn_type'] == "subscr_failed") { $new_status = "Refund"; $brief_description = 'PayPal has reported that the installment payment has failed.'; } elseif ($_POST['txn_type'] == "subscr_signup") { $new_status = "Other"; $brief_description = 'PayPal notified us that you signed up for an installment plan. Invoice updated to include installment convenience charge.'; } elseif ($_POST['txn_type'] == "subscr_payment") { $new_status = "Completed"; $brief_description = 'We have received an installment payment of $'.$_POST['payment_gross'].'.'; } elseif ($_POST['payment_status'] == "Pending") { $new_status = "Pending"; $brief_description = 'Your order has been processed and is pending for the following reason: '.$this->db_sanitized_fields['pending_reason']; } elseif ($_POST['payment_status'] == "Completed" || $_POST['payment_status'] == "Processed") { $new_status = "Completed"; $brief_description = 'We have received payment.'; } elseif (strlen($new_status) == 0) { $new_status = "Other"; $brief_description = 'The transaction reported a condition we did not expect. Please contact customer support at support at teratask dot com.'; } } } } $paypal_processor = new PayPalIPN($paypal_email); $paypal_processor->processIPN(); ?>
I can't build the whole implementation for you as that's something I get paid to do, but this should give you a large head start. The code is a bit old for me, so some of the techniques you've seen me encourage elsewhere aren't fully implemented here (e.g. quote_smart() and using switch instead of if/else), but it does work within my system and my goal was to give you some guidance which when coupled with the PayPal documentation will allow you to customize things for your own methodology.
__________________
Jeremy Miller
Please login or register to view this content. Registration is FREE
Last edited by JeremyMiller; 01-11-2008 at 03:44 PM..
|