Difference between revisions of "Extension:PayPal.php"
(update) |
|||
Line 1: | Line 1: | ||
<?php | <?php | ||
− | /* IpbWiki Paypal WikiMedia extension | + | /* IpbWiki Paypal WikiMedia extension |
** IpbWiki (c) 2006 | ** IpbWiki (c) 2006 | ||
** Installation Instructions: http://www.ipbwiki.com/IpbWiki_Paypal_Extension | ** Installation Instructions: http://www.ipbwiki.com/IpbWiki_Paypal_Extension | ||
Line 60: | Line 60: | ||
$query = "CREATE TABLE $wgPayPalIPNTable (id INTEGER NOT NULL, total_donated NUMERIC, total_donations INTEGER, PRIMARY KEY (id));"; | $query = "CREATE TABLE $wgPayPalIPNTable (id INTEGER NOT NULL, total_donated NUMERIC, total_donations INTEGER, PRIMARY KEY (id));"; | ||
$result = $db->query($query); | $result = $db->query($query); | ||
− | |||
− | |||
− | |||
} | } | ||
} | } | ||
Line 73: | Line 70: | ||
} | } | ||
− | # If this is an IPN post from paypal, update the DB | + | # If this is an IPN post from paypal, validate and update the DB if verified |
− | + | if (isset($_REQUEST['ipn'])) { | |
− | if ($_REQUEST[' | + | |
− | $item = isset($_REQUEST['item_number']) ? $_REQUEST['item_number'] : 1; | + | # Disable normal wiki rendering and output |
− | + | global $wgOut; | |
− | + | $wgOut->disable(); | |
− | + | wfResetOutputBuffers(); | |
− | + | ||
+ | # Read the post from PayPal system and add 'cmd' | ||
+ | $req = 'cmd=_notify-validate'; | ||
+ | foreach ($_POST as $k => $v) $req .= "&$k=".urlencode(stripslashes($v)); | ||
+ | |||
+ | # Post back to PayPal system (or sandbox if testing) 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"; | ||
+ | $domain = $wgPayPalTest ? 'www.sandbox.paypal.com' : 'www.paypal.com'; | ||
+ | $fp = fsockopen ($domain, 80, $errno, $errstr, 30); | ||
+ | if (!$fp) echo("http error"); # todo: log http error | ||
+ | else { | ||
+ | fputs($fp, $header . $req); | ||
+ | while (!feof($fp)) $res = fgets($fp, 1024); | ||
+ | if (strcmp ($res, "VERIFIED") == 0) { | ||
+ | // check 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 | ||
+ | $item = isset($_REQUEST['item_number']) ? $_REQUEST['item_number'] : 1; | ||
+ | $result = $db->query("SELECT CREATE TABLE $wgPayPalIPNTable;"); | ||
+ | if ($result instanceof ResultWrapper) $result = $result->result; | ||
+ | if ($row = $db->fetchRow($result)) { | ||
+ | #$row[0] # todo | ||
+ | } | ||
+ | } | ||
+ | elseif (strcmp($res, "INVALID") == 0) echo("Invalid"); # todo: log invalid | ||
} | } | ||
+ | fclose ($fp); | ||
} | } | ||
} | } | ||
Line 139: | Line 166: | ||
# Add a notify_url value in the form to tell paypal to post account changes to this script | # Add a notify_url value in the form to tell paypal to post account changes to this script | ||
− | $form = str_replace('</form>',"<input type=\"hidden\" name=\"notify_url\" value=\" | + | # todo: append shared secret to notify url |
+ | $notify_url = urlencode(stripslashes("$wgServer$wgScript?ipn")); | ||
+ | $form = str_replace('</form>',"<input type=\"hidden\" name=\"notify_url\" value=\"notify_url\" /></form>",$form); | ||
# Replace $1 and $2 in the text with the total amount donated and the total number of donations | # Replace $1 and $2 in the text with the total amount donated and the total number of donations |
Revision as of 11:24, 6 December 2007
<?php /* IpbWiki Paypal WikiMedia extension
- IpbWiki (c) 2006
- Installation Instructions: http://www.ipbwiki.com/IpbWiki_Paypal_Extension
Changes by User:Nad (1.0.3 - 2007-12-04):
- Added IPN support - Added ability to have a amount box - Change button definitions to work from LocalSettings rather than code hack - Output warnings into sitenotice in error box
- /
if (!defined('MEDIAWIKI')) die('Not an entry point.');
define('PAYPAL_VERSION','1.0.3, 2007-12-04');
$wgPayPalAmount = false; # Add an input field to enter the amount to donate
$wgPayPalIPN = false; # Use IPN notification
$wgPayPalTest = false; # Set to true if testing IPN in the PayPal sandbox site
$wgExtensionCredits['parserhook'][] = array(
'name' => 'IpbWiki PayPal',
'version' => PAYPAL_VERSION,
'author' => 'Peter De Decker, (IPN support by User:Nad)',
'url' => 'http://www.ipbwiki.com/IpbWiki_Paypal_Extension',
'description' => 'Mediawiki PayPal Extension'
);
$ipbwiki_paypal = array(); $wgExtensionFunctions[] = "wfPayPalExtension";
- Set up the extension
function wfPayPalExtension() { global $wgParser, $ipbwiki_paypal, $wgPayPalIPN;
# Register the extension with the WikiText parser $wgParser->setHook( "paypal", "wfPayPalRenderButton" );
# Set button 1 to a default value if not defined if (!isset($ipbwiki_paypal[1])) $ipbwiki_paypal[1] = '<form action="https://www.paypal.com/cgi-bin/webscr" method="post"><input type="hidden" name="cmd" value="_xclick"><input type="hidden" name="business" value="ipbwiki@gmail.com"><input type="hidden" name="item_name" value="IpbWiki PayPal"><input type="hidden" name="no_shipping" value="1"><input type="hidden" name="cn" value="Optional Comments"><input type="hidden" name="currency_code" value="EUR"><input type="hidden" name="tax" value="0"><input type="hidden" name="bn" value="PP-DonationsBF"><input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but04.gif" border="0" name="submit" alt="Make payments with PayPal - it\'s fast, free and secure!"></form>';
# IPN if ($wgPayPalIPN) {
global $wgHooks, $wgPayPalTest, $wgPayPalIPNTable, $wgUseAjax; $db = &wfGetDB(DB_MASTER);
# If using AJAX add JS updater after page rendered, and add the updater to the allowed AJAX functions if ($wgUseAjax) { $wgAjaxExportList[] = 'wfPayPalAjaxUpdater'; $wgHooks['OutputPageBeforeHTML'][] = 'wfPayPalAddAjaxUpdater'; }
# Create the IPN database table if it doesn't exist $wgPayPalIPNTable = $db->tableName('PayPalIPN'); if (!$db->tableExists($wgPayPalIPNTable)) { $query = "CREATE TABLE $wgPayPalIPNTable (id INTEGER NOT NULL, total_donated NUMERIC, total_donations INTEGER, PRIMARY KEY (id));"; $result = $db->query($query); } }
# If the table couldn't be created, disable IPN and add error to site notice if (!$db->tableExists($wgPayPalIPNTable)) { global $wgSiteNotice; $wgPayPalIPN = false;
$wgSiteNotice = "
Please ensure the wiki database user has CREATE permission, or add the table manually with the following query:
$query
";
}
# If this is an IPN post from paypal, validate and update the DB if verified if (isset($_REQUEST['ipn'])) {
# Disable normal wiki rendering and output global $wgOut; $wgOut->disable(); wfResetOutputBuffers();
# Read the post from PayPal system and add 'cmd' $req = 'cmd=_notify-validate'; foreach ($_POST as $k => $v) $req .= "&$k=".urlencode(stripslashes($v));
# Post back to PayPal system (or sandbox if testing) 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"; $domain = $wgPayPalTest ? 'www.sandbox.paypal.com' : 'www.paypal.com'; $fp = fsockopen ($domain, 80, $errno, $errstr, 30); if (!$fp) echo("http error"); # todo: log http error else { fputs($fp, $header . $req); while (!feof($fp)) $res = fgets($fp, 1024); if (strcmp ($res, "VERIFIED") == 0) { // check 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 $item = isset($_REQUEST['item_number']) ? $_REQUEST['item_number'] : 1; $result = $db->query("SELECT CREATE TABLE $wgPayPalIPNTable;"); if ($result instanceof ResultWrapper) $result = $result->result; if ($row = $db->fetchRow($result)) { #$row[0] # todo } } elseif (strcmp($res, "INVALID") == 0) echo("Invalid"); # todo: log invalid } fclose ($fp); } }
}
- The callback function for converting the input text to HTML output
function wfPayPalRenderButton( $input, $argv ) { global $ipbwiki_paypal, $wgAuth, $wgSiteNotice, $wgPayPalIPN;
$error = '
';
$pos_space = strpos($input,' '); if (!$pos_space) { if (is_numeric($input)) { // format <paypal>number</paypal> $part1 = $input; $part2 = ; if (!$ipbwiki_paypal[$part1]) { $wgSiteNotice .= $error; $part1 = 1; $part2 = $input; } } else { // format <paypal>text</paypal> & format <paypal></paypal> $part1 = 1; $part2 = $input; } } else { // format <paypal>number text</paypal> $part1 = substr($input,0,$pos_space); $part2 = substr($input,$pos_space+1); if (is_numeric($part1)) { if (!$ipbwiki_paypal[$part1]) { $wgSiteNotice .= $error; $part1 = 1; } } else { // format <paypal>text</paypal> $part1 = 1; $part2 = $input; } } $form = $ipbwiki_paypal[$part1]; // if the ipbwiki interface is available, then use the clean function which is defined there, otherwise just clean the necessities... if (class_exists ('ipbwiki')) { $input = $wgAuth->ipbwiki->ipbwiki->clean_value ($part2); } else { $part2 = str_replace( ">", ">", $part2 ); $part2 = str_replace( "<", "<", $part2 ); $part2 = str_replace( "\"", """, $part2 ); $part2 = str_replace( "!", "!", $part2 ); $part2 = str_replace( "'", "'", $part2 ); $input = $part2; }
# IPN if ($wgPayPalIPN) { global $wgPayPalIPNTable, $wgPayPalTest, $wgServer, $wgScript, $wgPayPalItemsRendered;
# Change the paypal URL's to sandbox site if testing if ($wgPayPalTest) $form = str_replace('www.paypal.com','www.sandbox.paypal.com',$form);
# Add a notify_url value in the form to tell paypal to post account changes to this script # todo: append shared secret to notify url $notify_url = urlencode(stripslashes("$wgServer$wgScript?ipn")); $form = str_replace('</form>',"<input type=\"hidden\" name=\"notify_url\" value=\"notify_url\" /></form>",$form);
# Replace $1 and $2 in the text with the total amount donated and the total number of donations # - these values are surrounded by div's endowed with id's so that the AJAX updater can access them $db = &wfGetDB(DB_SLAVE); $result = $db->query("SELECT id,total_donated,total_donations FROM $wgPayPalIPNTable WHERE id = '$part1'"); if ($result instanceof ResultWrapper) $result = $result->result; if ($row = $db->fetchRow($result)) {
$total_donated = "
"; $total_donations = "
";
} $input = wfMsgReplaceArgs($input,array($total_donated,$total_donations)); }
$output = '
'.$form.' | '.$input.' |
';
return $output; }
- Adds a JS function to poll for changes to any of the button's totals
function wfPayPalAddAjaxUpdater(&$out) { global $wgJsMimeType; $out->addScript("<script type='$wgJsMimeType'> function workflowUpdateState(name) { clearTimeout(workflowUpdate); workflowLastState = workflowData[name][0]; var state = workflowData[name][workflowLastState]; sajax_do_call('wfPayPalAjaxUpdater',[wgPageName,name,state],document.getElementById('catlinks')); } function workflowSwitchState(name,dir) { clearTimeout(workflowUpdate); document.getElementById('workflow-'+name+'-'+state).setAttribute('style',); if (workflowLastState != state) workflowUpdate = setTimeout('workflowUpdateState(\"'+name+'\")',$wgWorkflowUpdateDelay); } </script>"); return true; }
- The function called by the AJAX dispatcher to return the current totals of all buttons
function wfPayPalAjaxUpdater() { # todo: just return all the items in the db return $something; }