How to Process PayPal Instant Payment Notification (IPN) with PHP
I have worked on numerous sites that had a need to collect either a one-time payment or establish a recurring (subscription) payment. I always recommend PayPal for collecting payments. PayPal not only offers the ability to make payment with PayPal but also allows non-PayPal buyers to pay with a debit or credit card. There is no charge to join PayPal and no monthly fee to use their service. There is only a charge when you receive a payment. Most clients I work with like not having to pay until you use it.
It is very simple to set up a PayPal payment form to collect payment. The form is nothing more than a button that takes the buyer to PayPal to complete payment then returns them to your site when done. I like to display some information above the button so the buyer has an idea of what they are buying and how much it will cost.
This is a two-part process. The first step is to prompt the buyer for payment via PayPal. The second step is to receive the PayPal Instant Payment Notification (IPN) Post. The IPN post will occur everytime a payment is made, this includes recurring payments. This can be super useful for membership subscriptions. If a member must pay every month to maintain their subscription then we set them to expire 30 days after they join. If the recurring payment does not post then they expire. If the recurring payment does post then we extend the membership by one month.
Step 1 – The PayPal payment form. Our form is for recurring payments that recur every month. The form input a3 indicates the monthly recurring amount, input p3 indicates the recurring interval, and input t3 indicates the interval type. Our form also includes a free trial period of 7 days. The form input a1 indicates the trial period amount, input p1 indicates the trial period interval, and input t1 indicates the trial interval type. We store the member id in the form input field named custom and an invoice id in the form input field named invoice. These two field values, along with other fields, will be sent back in the IPN. We can use these fields to identify our member or order or whatever you need to tie the payment to. I’ve also built pipe delimited string values for the invoice field so I can store multiple values. For example, 11|22|33 for subscription 11, listing 22, advertisement 33.
The field notify_url indicates where PayPal will send the IPN. This should be a URL on your site that processes the IPN post from PayPal. See part 2 below for the IPN post.
<?php $member_id = 12345; $invoice_id = "987654321"; ?> <p>Thank you for joining Example.com.</p> <br>Example.com Monthly Subscription is: $25.00. <br>Payments will will begin after your 7 day free trial. <br>Payments will automatically bill each month until you cancel. <br>Please proceed with your payment to complete your subscription. <br>Please allow up to 24 hours for your payment to post. <br>Once your payment has posted your profile will become active.</p> <form name='formPackage' action='https://www.paypal.com/cgi-bin/webscr' method='post'> <input type='hidden' name='cmd' value='_xclick-subscriptions'> <input type='hidden' name='business' value='YourPayPalEmailAddress'> <input type='hidden' name='notify_url' value='https://example.com/pp/processPayPalIPN.php'> <input type='hidden' name='return' value='https://example.com/'> <input type='hidden' name='cancel_return' value='https://example.com/'> <input type='hidden' name='currency_code' value='USD'> <input type='hidden' name='no_shipping' value='1'> <input type='hidden' name='no_note' value='1'> <input type='hidden' name='lc' value='US'> <input type='hidden' name='bn' value='PP-SubscriptionsBF'> <input type='hidden' name='item_name' value='Example.com subscription'> <input type='hidden' name='a1' value='0'> <input type='hidden' name='p1' value='7'> <input type='hidden' name='t1' value='D'> <input type='hidden' name='a3' value='25.00'> <input type='hidden' name='p3' value='1'> <input type='hidden' name='t3' value='M'> <input type='hidden' name='src' value='1'> <input type='hidden' name='sra' value='1'> // These are passthrough values for ID purposes <input type='hidden' name='custom' value='<?php echo $member_id ?>'> <input type='hidden' name='invoice' value='<?php echo $invoice_id ?>'> <input type='image' src='https://www.paypal.com/en_US/i/btn/btn_subscribe_LG.gif' border='0' name='submit' alt='Make payments with PayPal - it is fast, free and secure!'> </form>
Step 2 – The IPN post page. This is a very basic example of how to handle the PayPal IPN. Once you receive the IPN you will probably need to do something like update your database or email yourself to ship a product.
<?php if ($_POST) { // paypal posted fields $txn_type = strip_tags($_POST['txn_type']); $payment_type = strip_tags($_POST['payment_type']); $payment_status = strip_tags($_POST['payment_status']); $payment_date = strip_tags($_POST['payment_date']); $payment_gross = strip_tags($_POST['payment_gross']); $payment_fee = strip_tags($_POST['payment_fee']); $subscr_id = strip_tags($_POST['subscr_id']); $last_name = strip_tags($_POST['last_name']); $first_name = strip_tags($_POST['first_name']); $payer_email = strip_tags($_POST['payer_email']); $payer_id = strip_tags($_POST['payer_id']); $custom = strip_tags($_POST['custom']); $invoice = strip_tags($_POST['invoice']); // convert the member id from the custom field $member_id = (int)$custom; // payment completed - do something if (strtolower($payment_status) == "completed") { // do something - for example update your database to extend the membership or email yourself to ship your product to the customer. } } ?>
References
PayPal form basics
PHP echo
PHP strip_tags
PHP $_POST
PHP strtolower
PHP type juggling