Skip to content

Instantly share code, notes, and snippets.

@anointed
Created September 30, 2012 02:42
Show Gist options
  • Save anointed/3805698 to your computer and use it in GitHub Desktop.
Save anointed/3805698 to your computer and use it in GitHub Desktop.
Paypal multiple IPN's
<?php
/*
* This is a PayPal IPN (Instant Payment Notification) broadcaster
* Since PayPal does not provide any straightforward way to add
* multiple IPN listeners we'll have to create a central IPN
* listener that will broadcast (or filter and dispatch) Instant
* Payment Notifications to different destinations (IPN listeners)
*
* http://codeseekah.com/2012/02/11/how-to-setup-multiple-ipn-receivers-in-paypal/
*
* Destination IPN listeners must not panic and recognize IPNs sent
* by this central broadcast as valid ones in terms of source IP
* and any other fingerprints. Any IP filtering must add this host,
* other adjustments made as necessary.
*
* IPNs are logged into files for debugging and maintenance purposes
*
* this code comes with absolutely no warranty
*/
ini_set( 'max_execution_time', 0 ); /* Do not abort with timeouts */
ini_set( 'display_errors', 'Off' ); /* Do not display any errors to anyone */
$urls = array(); /* The broadcast session queue */
/* List of IPN listener points */
$ipns = array(
'mystore' => 'http://mystore.com/ipn.php',
'myotherstore' => 'http://mybigstore.com/paypal_ipn.php',
'myotherandbetterstore' => 'http://slickstore.com/paypal/ipn.php'
);
/* Fingerprints */
if ( /* My Store IPN Fingerprint */
preg_match( '#^\d+\|[a-f0-9]{32}$#', $_POST['custom'] ) /* Custom hash */
and $_POST['num_cart_items'] == 2 /* alwayst 1 item in cart */
and strpos( $_POST['item_name1'], 'MySite.com Product' ) == 0 /* First item name */
) $urls []= $ipns['mystore']; /* Choose this IPN URL if all conditions have been met */
if ( /* My Other Store IPN Fingerprint */
sizeof( explode('_', $_POST['custom']) ) == 7 /* has 7 custom pieces */
) $urls []= $ipns['myotherstore']; /* Choose this IPN URL if all conditions have been met */
/* My Other And Better Store IPN Fingerprint */
$custom = explode('|', $_POST['custom']);
if (
isset($custom[2]) and $custom[2] == 'FROM_OB_STORE' /* custom prefixes */
) $urls []= $ipns['myotherandbetterstore']; /* Choose this IPN URL if all conditions have been met */
/* ... */
/* Broadcast */
if ( !sizeof($urls) ) $urls = $ipns; /* No URLs have been matched */
$urls = array_unique( $urls ); /* Unique, just in case */
/* Broadcast (excluding IPNs from the list according to filter is possible */
foreach ( $urls as $url ) broadcast( $url );
header( 'HTTP/1.1 200 OK', true, 200 );
exit(); /* Thank you, bye */
/* Perform a simple cURL-powered proxy request to broadcast */
function broadcast( $url ) {
/* Format POST data accordingly */
$data = array();
foreach ($_POST as $key => $value) $data []= urlencode($key).'='.urlencode($value);
$data = implode('&', $data);
/* Log the broadcast */
file_put_contents('_logs/'.time().'.'.reverse_lookup( $url ).'-'.rand(1,100), $data);
$ch = curl_init(); /* Initialize */
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, count($data));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch); /* Execute HTTP request */
curl_close($ch); /* Close */
}
function reverse_lookup( $url ) {
global $ipns;
foreach ( $ipns as $tag => $_url ) {
if ( $url == $_url ) return $tag;
}
return 'unknown';
}
?>
@anointed
Copy link
Author

Wouldn’t it be safer and easier to just issue a 302/303 redirect instead of re-sending the data using curl?

@Graphicpoet
Copy link

Hey there.

I really need this but I am pretty green at this sort of stuff. So one BIG question. Can I delete this :

if ( /* My Store IPN Fingerprint _/
preg_match( '#^\d+|[a-f0-9]{32}$#', $POST['custom'] ) / Custom hash _/
and $POST['num_cart_items'] == 2 / alwayst 1 item in cart _/
and strpos( $POST['item_name1'], 'MySite.com Product' ) == 0 / First item name /
) $urls []= $ipns['mystore']; /
Choose this IPN URL if all conditions have been met */

if ( /* My Other Store IPN Fingerprint */
    sizeof( explode('_', $_POST['custom']) ) == 7 /* has 7 custom pieces */
) $urls []= $ipns['myotherstore']; /* Choose this IPN URL if all conditions have been met */

AND JUST KEEP THIS ONE BELOW AND DUPLICATE IT FOR EACH IPN? :

/* My Other And Better Store IPN Fingerprint _/
$custom = explode('|', $POST['custom']);
if (
isset($custom[2]) and $custom[2] == 'FROM_OB_STORE' /
custom prefixes /
) $urls []= $ipns['myotherandbetterstore']; /
Choose this IPN URL if all conditions have been met */

/* ... */


/* Broadcast */

Thanks in advance even if you get this....

M. Byrd

@garyvenrooy
Copy link

That worked great! Thank you!

@yanyan001
Copy link

Hi, can i ask the procedure on where to put that code in my wordpress server? My problem is, i have a LIST on my mailchimp wherein after purchasing thru paypal, the details(especially email) of the customer will be added to the list of subscribers on mailchimp. But then i have 2 lists and the problem is, paypal only allows 1 IPN. Can you help me on this?? I badly need your help :(

@gino8080
Copy link

gino8080 commented Jul 1, 2016

Great stuff that works!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment