r54612 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r54611‎ | r54612 | r54613 >
Date:21:31, 7 August 2009
Author:diana
Status:deferred
Tags:
Comment:
Initial commit of C2P2 project extensions.
Modified paths:
  • /trunk/extensions/DonationInterface/donate_interface (added) (history)
  • /trunk/extensions/DonationInterface/donate_interface/donate_interface.il8n.php (added) (history)
  • /trunk/extensions/DonationInterface/donate_interface/donate_interface.php (added) (history)
  • /trunk/extensions/DonationInterface/donate_interface/donate_interface.setup.php (added) (history)
  • /trunk/extensions/DonationInterface/donate_interface/validate_donation.js (added) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway (added) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/includes (added) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/includes/countryCodes.inc (added) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/includes/payflowUser.inc (added) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/includes/stateAbbreviations.inc (added) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.alias.php (added) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.body.php (added) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.i18n.php (added) (history)
  • /trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.php (added) (history)
  • /trunk/extensions/DonationInterface/paypal_gateway (added) (history)
  • /trunk/extensions/DonationInterface/paypal_gateway/paypal_gateway.il8n.php (added) (history)
  • /trunk/extensions/DonationInterface/paypal_gateway/paypal_gateway.php (added) (history)

Diff [purge]

Index: trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.alias.php
@@ -0,0 +1,8 @@
 2+<?php
 3+$aliases = array();
 4+
 5+/** English */
 6+$aliases['en'] = array(
 7+ 'PayflowProGateway' => array( 'PayflowProGateway' ),
 8+);
 9+
Index: trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.body.php
@@ -0,0 +1,536 @@
 2+<?php
 3+class PayflowProGateway extends SpecialPage {
 4+ function __construct() {
 5+ parent::__construct( 'PayflowProGateway', $restriction = '', $listed = false );
 6+
 7+ wfLoadExtensionMessages('PayflowProGateway');
 8+ }
 9+
 10+ function execute( $par ) {
 11+ global $wgRequest, $wgOut, $wgUser;
 12+
 13+ global $wgParser;
 14+ $wgParser->disableCache();
 15+
 16+
 17+ $this->setHeaders();
 18+
 19+ //create token if one doesn't already exist
 20+ $token = $wgUser->editToken('mrxc877668DwQQ');
 21+
 22+ // Declare form post variables
 23+ $data = array(
 24+ 'amount' => '',
 25+ 'email' => '',
 26+ 'fname' => '',
 27+ 'mname' => '',
 28+ 'lname' => '',
 29+ 'street' => '',
 30+ 'city' => '',
 31+ 'state' => '',
 32+ 'zip' => '',
 33+ 'country' => '',
 34+ 'card_num' => '',
 35+ 'expiration' => '',
 36+ 'cvv' => '',
 37+ 'currency' => '',
 38+ 'payment_method' => '',
 39+ );
 40+
 41+ $error[] = '';
 42+
 43+ //find out if amount was a radio button or textbox, set amount
 44+ if (isset($_REQUEST['amount'])) {
 45+ $amount = number_format($wgRequest->getText('amount'), 2);
 46+ } else if (isset($_REQUEST['amount2'])) {
 47+ $amount = number_format($wgRequest->getText('amount2'), 2, '.', '');
 48+ } else {
 49+ $wgOut->addHTML("This page is only accessible from the donation page");
 50+ return;
 51+ }
 52+
 53+ // Populate from data
 54+ $data = array(
 55+ 'amount' => $amount,
 56+ 'email' => $wgRequest->getText('email'),
 57+ 'fname' => $wgRequest->getText('fname'),
 58+ 'mname' => $wgRequest->getText('mname'),
 59+ 'lname' => $wgRequest->getText('lname'),
 60+ 'street' => $wgRequest->getText('street'),
 61+ 'city' => $wgRequest->getText('city'),
 62+ 'state' => $wgRequest->getText('state'),
 63+ 'zip' => $wgRequest->getText('zip'),
 64+ 'country' => $wgRequest->getText('country'),
 65+ 'card' => $wgRequest->getText('card'),
 66+ 'card_num' => str_replace(' ','',$wgRequest->getText('card_num')),
 67+ 'expiration' => $wgRequest->getText('mos').substr($wgRequest->getText('year'), 2, 2),
 68+ 'cvv' => $wgRequest->getText('cvv'),
 69+ 'currency' => $wgRequest->getText('currency_code'),
 70+ 'payment_method' => $wgRequest->getText('payment_method'),
 71+ 'token' => $wgRequest->getVal('token'),
 72+ 'test_string' => $wgRequest->getText('process') //for showing payflow string during testing
 73+ );
 74+
 75+
 76+ // Get array of default account values necessary for Payflow
 77+ require_once('includes/payflowUser.inc');
 78+
 79+ $payflow_data = payflowUser();
 80+
 81+ // Check form for errors and display
 82+ // match token
 83+ $success = $wgUser->matchEditToken($token, 'mrxc877668DwQQ');
 84+
 85+ if ($success) {
 86+ if ($data['payment_method'] == "processed") {
 87+ // Check form for errors and redisplay with messages
 88+ if ($form_errors = $this->validateForm($data, $error)) {
 89+ $this->displayForm($data, $error);
 90+ } else {
 91+ // The submitted data is valid, so process it
 92+ $this->processTransaction($data, $payflow_data);
 93+ }
 94+ }
 95+ else {
 96+ //Display form for the first time
 97+ $this->displayForm($data, $error);
 98+ }
 99+ } // end $success
 100+
 101+}
 102+
 103+ /*
 104+ * Displays form to user
 105+ *
 106+ * @params
 107+ * $data array of posted user input
 108+ * $error array of error messages returned by validate_form function
 109+ *
 110+ * Form can be output as a table or as a fieldset. Fieldset is commented out by default. Both include class names.
 111+ *
 112+ * The message at the top of the form can be edited in the payflow_gateway.i18.php file
 113+ */
 114+ private function displayForm($data, &$error) {
 115+ require_once('includes/stateAbbreviations.inc');
 116+ require_once('includes/countryCodes.inc');
 117+
 118+ global $wgOut;
 119+
 120+ $form = wfMsg('form-message');
 121+
 122+ //show error messages if they exist
 123+ if (!empty($error)) {
 124+ //add styling
 125+ $form .= '<div class="creditcard_error">';
 126+ foreach($error as $key) {
 127+ $form .= '<p class="creditcard_error_msg">'.$key.'</p>';
 128+ }
 129+ $form .= '</div>';
 130+ }
 131+
 132+ //create drop down of countries
 133+ //$countries = $this->countryCodes();
 134+ $countries = countryCodes();
 135+
 136+ foreach($countries as $key => $value) {
 137+ $countryMenu .= '<option value='. $key . '>'. $value .'</option>';
 138+ }
 139+
 140+ //Form implemented as a table with classnames
 141+ //***Comment this section out and uncomment the subsequent implementation as a fieldset if preferred***
 142+ $form .='<div class="mw-creditcard_form"><form name="payment" method="post" action="">
 143+ <table class="mw-creditcard_table" border="0" cellspacing="1" cellpadding="3">
 144+ <tr><td class="mw-mw-creditcard-label">Donation Amount: </td><td class="mw-mw-creditcard-input">'.$data['amount'].'</td></tr>
 145+ <input type="hidden" name="amount" value="'.$data['amount'].'">
 146+ <tr><td class="mw-creditcard-label">Donor Information:</td></tr>
 147+ <tr><td class="mw-creditcard-name">E-mail Address:</td>
 148+ <td class="mw-creditcard-input"><input type="text" name="email" value="'.$data['email'].'" maxlength="150" size="30" /></td></tr>
 149+ <tr><td class="mw-creditcard-name">First Name:</td>
 150+ <td class="mw-creditcard-input"><input type="text" name="fname" value="'.$data['fname'].'" maxlength="35" size="20" /></td></tr>
 151+ <tr><td class="mw-creditcard-name">Middle Name:</td>
 152+ <td class="mw-creditcard-input"><input type="text" name="mname" value="'.$data['mname'].'" maxlength="35" size="20" /></td></tr>
 153+ <tr><td class="mw-creditcard-name">Last Name:</td>
 154+ <td class="mw-creditcard-input"><input type="text" name="lname" value="'.$data['lname'].'" maxlength="35" size="20" /></td></tr>
 155+ <tr><td class="mw-creditcard-name">Street:</td>
 156+ <td class="mw-creditcard-input"><input type="text" name="street" value="'.$data['street'].'" maxlength="100" size="30" /></td></tr>
 157+ <tr><td class="mw-creditcard-name">City:</td>
 158+ <td class="mw-creditcard-input"><input type="text" name="city" value="'.$data['city'].'" maxlength="35" size="20" /></td></tr>
 159+ <tr><td class="mw-creditcard-name">State:</td>
 160+ <td class="mw-creditcard-input"><select name="state" value="'.$data['state'].'" />'. statesMenu() .'</td></tr>
 161+ <tr><td class="mw-creditcard-name">Postal Code:</td>
 162+ <td class="mw-creditcard-input"><input type="text" name="zip" value="'.$data['zip'].'" maxlength="18" size="15" /></td></tr>
 163+ <tr><td class="mw-creditcard-name">Country/Region:</td>
 164+ <td class="mw-creditcard-input"><select name="country" value="'.$data['country'].'" />'.$countryMenu.'</select></td></tr>
 165+ <tr><td class="mw-creditcard-label">Credit Card Information:</td></tr>
 166+ <tr><td class="mw-creditcard-name">Credit Card:</td>
 167+ <td class="mw-creditcard-input"><select name="card">
 168+ <option value="visa">Visa</option><option selected="selected" value="mastercard">MasterCard</option>
 169+ <option value="american">American Express</option></select></td></tr>
 170+ <tr><td class="mw-creditcard-name">Card Number: </td>
 171+ <td class="mw-creditcard-input"><input type="text" name="card_num" maxlength="100" /></td></tr>
 172+ <tr><td class="mw-creditcard-name">Expiration Date:</td><td class="mw-creditcard-input">
 173+ <select name="mos">
 174+ <option value="01">01</option>
 175+ <option value="02">02</option>
 176+ <option value="03">03</option>
 177+ <option value="04">04</option>
 178+ <option value="05">05</option>
 179+ <option value="06">06</option>
 180+ <option value="07">07</option>
 181+ <option value="08">08</option>
 182+ <option value="09">09</option>
 183+ <option value="10">10</option>
 184+ <option value="11">11</option>
 185+ <option value="12" selected="selected">12</option>
 186+ </select>
 187+ <select name="year">
 188+ <option value="'.(date('Y')).'">'.(date('Y')).'</option>
 189+ <option value="'.(date('Y')+1).'">'.(date('Y')+1).'</option>
 190+ <option value="'.(date('Y')+2).'" selected="selected">'.(date('Y')+2).'</option>
 191+ <option value="'.(date('Y')+3).'">'.(date('Y')+3).'</option>
 192+ <option value="'.(date('Y')+4).'">'.(date('Y')+4).'</option>
 193+ <option value="'.(date('Y')+5).'">'.(date('Y')+5).'</option>
 194+ <option value="'.(date('Y')+6).'">'.(date('Y')+6).'</option>
 195+ <option value="'.(date('Y')+7).'">'.(date('Y')+7).'</option>
 196+ <option value="'.(date('Y')+8).'">'.(date('Y')+8).'</option>
 197+ <option value="'.(date('Y')+9).'">'.(date('Y')+9).'</option>
 198+ <option value="'.(date('Y')+10).'">'.(date('Y')+10).'</option>
 199+ </select></td></tr>
 200+ <tr><td class="mw-creditcard-name">Card Security Code:</td><td class="mw-creditcard-input"><input type="text" name="cvv" size="5" maxlength="35" /></td></tr>
 201+ <tr><td>
 202+ <input type="hidden" name="process" value="CreditCard" />
 203+ <input type="hidden" name="payment_method" value="processed" />
 204+ <input type="hidden" name="token" value="'.$data['token'].'">
 205+ <input type="hidden" name="currency_code" value="'.$data['currency'].'" />
 206+ <input type="hidden" name="orderid" value="'.$data['order_id'].'" /></td>
 207+ <td><input type="submit" value=" Donate " /></td></tr>
 208+ </table>
 209+ </form></div>
 210+ </div>';
 211+
 212+ //Implemented as a form with fieldsets
 213+ //***Uncomment this section and comment out the previous table implementation if preferred***
 214+ /*
 215+ $form .= '<div class="mw-creditcard-form">
 216+ <form name="payment" method="post" action="">
 217+ <legend class="mw-creditcard-amount">Donation Amount: '.$data['amount'].'</legend>
 218+ <input type="hidden" name="amount" value="'.$data['amount'].'">
 219+ <fieldset class="mw-creditcard-donor">
 220+ <legend>Donor Information:</legend>
 221+ <p><label>E-mail Address:</label><input type="text" name="email" value="'.$data['email'].'" maxlength="150" size="30" /></p>
 222+ <p><label>First Name:</label><input type="text" name="fname" value="'.$data['fname'].'" maxlength="35" size="20" /></p>
 223+ <p><label>Middle Name:</label><input type="text" name="mname" value="'.$data['mname'].'" maxlength="35" size="20" /></p>
 224+ <p><label>Last Name:</label><input type="text" name="lname" value="'.$data['lname'].'" maxlength="35" size="20" /></p>
 225+ <p><label>Street:</label><input type="text" name="street" value="'.$data['street'].'" maxlength="100" size="30" /></p>
 226+ <p><label>City:</label><input type="text" name="city" value="'.$data['city'].'" maxlength="35" size="20" /></p>
 227+ <p><label>State:</label><select name="state" value="'.$data['state'].'" />'. statesMenu() .'</select></p>
 228+ <p><label>Postal Code:</label><input type="text" name="zip" value="'.$data['zip'].'" maxlength="18" size="15" /></p>
 229+ <p><label>Country/Region:</label><select name="country" value="'.$data['country'].'" />'.$countryMenu.'</select></p>
 230+ </fieldset>
 231+ <fieldset class="mw-creditcard-label">
 232+ <legend>Credit Card Information:</legend>
 233+ <p><label>Credit Card:</label>
 234+ <select name="card">
 235+ <option value="visa">Visa</option><option selected="selected" value="mastercard">MasterCard</option>
 236+ <option value="american">American Express</option>
 237+ </select></p>
 238+ <p><label>Card Number: </label><input type="text" name="card_num" maxlength="100" /></p>
 239+ <p><label>Expiration Date:</label>
 240+ <select name="mos">
 241+ <option value="01">01</option><option value="02">02</option><option value="03">03</option><option value="04">04</option>
 242+ <option value="05">05</option><option value="06">06</option><option value="07">07</option><option value="08">08</option>
 243+ <option value="09">09</option><option value="10">10</option><option value="11">11</option><option value="12" selected="selected">12</option>
 244+ </select>
 245+ <select name="year">
 246+ <option value="'.(date('Y')).'">'.(date('Y')).'</option>
 247+ <option value="'.(date('Y')+1).'">'.(date('Y')+1).'</option>
 248+ <option value="'.(date('Y')+2).'" selected="selected">'.(date('Y')+2).'</option>
 249+ <option value="'.(date('Y')+3).'">'.(date('Y')+3).'</option>
 250+ <option value="'.(date('Y')+4).'">'.(date('Y')+4).'</option>
 251+ <option value="'.(date('Y')+5).'">'.(date('Y')+5).'</option>
 252+ <option value="'.(date('Y')+6).'">'.(date('Y')+6).'</option>
 253+ <option value="'.(date('Y')+7).'">'.(date('Y')+7).'</option>
 254+ <option value="'.(date('Y')+8).'">'.(date('Y')+8).'</option>
 255+ <option value="'.(date('Y')+9).'">'.(date('Y')+9).'</option>
 256+ <option value="'.(date('Y')+10).'">'.(date('Y')+10).'</option>
 257+ </select></p>
 258+ <p><label>Card Security Code:</label><input type="text" name="cvv" size="5" maxlength="35" /></p>
 259+ <input type="hidden" name="process" value="CreditCard" />
 260+ <input type="hidden" name="payment_method" value="processed" />
 261+ <input type="hidden" name="token" value="'.$data['token'].'">
 262+ <input type="hidden" name="currency_code" value="'.$data['currency'].'" />
 263+ <input type="hidden" name="orderid" value="'.$data['order_id'].'" />
 264+ <input type="submit" value=" Donate " />
 265+ </fieldset>
 266+ </form>
 267+ </div>
 268+ </div>';
 269+ */
 270+
 271+ $wgOut->addHTML( $form );
 272+ $wgOut->addHTML('<p class="mw-creditcard-submessage">This donation is being made in ' .$data['currency'] . '</p>');
 273+
 274+ }
 275+
 276+
 277+ /*
 278+ * Checks posted form data for errors and returns array of messages
 279+ */
 280+ private function validateForm($data, &$error) {
 281+ global $wgOut;
 282+
 283+ //begin with no errors
 284+ $error_result = '0';
 285+
 286+ //create the human-speak message for required fields
 287+ //does not include fields that are not required
 288+ $msg = array(
 289+ 'amount' => "donation amount",
 290+ 'email' => "email address",
 291+ 'fname' => "first name",
 292+ 'lname' => "last name",
 293+ 'street' => "street address",
 294+ 'city' => "city",
 295+ 'state' => "state",
 296+ 'zip' => "zip code",
 297+ 'card_num' => "credit card number",
 298+ 'expiration' => "card's expiration date",
 299+ 'cvv' => "the CVV from the back of your card",
 300+ );
 301+
 302+ //find all empty fields and create message
 303+ foreach($data as $key => $value) {
 304+ if ($value == '') {
 305+ //ignore fields that are not required
 306+ if ($msg[$key]) {
 307+ $error[$key] = "**Please enter your " . $msg[$key] . "**<br />";
 308+ $error_result = '1';
 309+ }
 310+ }
 311+ }
 312+
 313+ //is email address valid?
 314+ $isEmail = eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $data['email']);
 315+
 316+ //create error message (supercedes empty field message)
 317+ if (!$isEmail) {
 318+ $error['email'] = "**Please enter a valid email address**";
 319+ $error_result = '1';
 320+ }
 321+
 322+ //validate that credit card number entered is correct for the brand
 323+ switch($data['card'])
 324+ {
 325+ case 'american' :
 326+ //pattern for Amex
 327+ $pattern = "/^([34|37]{2})([0-9]{13})$/";
 328+
 329+ //if the pattern doesn't match
 330+ if (!preg_match($pattern,$data['card_num'])) {
 331+ $error_result = '1';
 332+ $error['card'] = "**Please enter a correct card number for American Express.**";
 333+ }
 334+ break;
 335+
 336+ case 'mastercard' :
 337+ //pattern for Mastercard
 338+ $pattern = "/^([51|52|53|54|55]{2})([0-9]{14})$/";
 339+
 340+ //if pattern doesn't match
 341+ if (!preg_match($pattern,$data['card_num'])) {
 342+ $error_result = '1';
 343+ $error['card'] = "**Please enter a correct card number for Mastercard.**";
 344+ }
 345+ break;
 346+
 347+ case 'visa' :
 348+ //pattern for Visa
 349+ $pattern = "/^([4]{1})([0-9]{12,15})$/";
 350+
 351+ //if pattern doesn't match
 352+ if (!preg_match($pattern,$data['card_num'])) {
 353+ $error_result = '1';
 354+ $error['card'] = "**Please enter a correct card number for Visa.**";
 355+ }
 356+ break;
 357+ }//end switch*/
 358+
 359+ return $error_result;
 360+ }
 361+
 362+
 363+ /*
 364+ * Sends a name-value pair string to Payflow gateway
 365+ *
 366+ * parameters:
 367+ * $data array of user input
 368+ * $payflow_data array of necessary Payflow variables to include in string (ie Vendor, password)
 369+ *
 370+ */
 371+ private function processTransaction($data, $payflow_data) {
 372+ global $wgOut;
 373+
 374+ /* Create name-value pair query string */
 375+ $payflow_query = "TRXTYPE=$payflow_data[trxtype]&TENDER=$payflow_data[tender]&USER=$payflow_data[user]&VENDOR=$payflow_data[vendor]&PARTNER=$payflow_data[partner]&PWD=$payflow_data[password]&ACCT=$data[card_num]&EXPDATE=$data[expiration]&AMT=$data[amount]&FIRSTNAME=$data[fname]&LASTNAME=$data[lname]&STREET=$data[street]&ZIP=$data[zip]&INVNUM=$payflow_data[order_id]&CVV2=$data[cvv]&CURRENCY=$data[currency]&VERBOSITY=$payflow_data[verbosity]&CUSTIP=$payflow_data[user_ip]";
 376+
 377+ // assign header data necessary for the curl_setopt() function
 378+ $user_agent = $_SERVER['HTTP_USER_AGENT'];
 379+ $headers[] = "Content-Type: text/xml";
 380+ $headers[] = "Content-Length : " . strlen ($payflow_query);
 381+ $headers[] = "X-VPS-Timeout: 45";
 382+ $headers[] = "X-VPS-Request-ID:" . $payflow_data['order_id'];
 383+
 384+ $ch = curl_init();
 385+ curl_setopt($ch, CURLOPT_URL, $payflow_data['testingurl']);
 386+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
 387+ curl_setopt($ch, CURLOPT_USERAGENT, $user_agent);
 388+ curl_setopt($ch, CURLOPT_HEADER, 1);
 389+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 390+ curl_setopt($ch, CURLOPT_TIMEOUT, 90);
 391+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
 392+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
 393+ curl_setopt($ch, CURLOPT_POSTFIELDS, $payflow_query);
 394+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
 395+ curl_setopt($ch, CURLOPT_FORBID_REUSE, TRUE);
 396+ curl_setopt($ch, CURLOPT_POST, 1);
 397+
 398+ // As suggested in the PayPal developer forum sample code, try more than once to get a response
 399+ // in case there is a general network issue
 400+ $i=1;
 401+ while ($i++ <= 3) {
 402+ $result = curl_exec($ch);
 403+ $headers = curl_getinfo($ch);
 404+ if ($headers['http_code'] != 200) {
 405+ sleep(5);
 406+ } else if ($headers['http_code'] == 200) {
 407+ break;
 408+ }
 409+ }
 410+
 411+ if ($headers['http_code'] != 200) {
 412+ $wgOut->addHTML('<h3>No response from credit card processor. Please try again later!</h3><p>');
 413+ curl_close($ch);
 414+ exit;
 415+ }
 416+
 417+ curl_close($ch);
 418+
 419+ // get result string
 420+ $result = strstr($result, "RESULT");
 421+
 422+ // parse string and display results to the user
 423+ $this->getResults($data, $result);
 424+
 425+ }
 426+
 427+
 428+ /*
 429+ * "Reads" the name-value pair result string returned by Payflow and creates corresponding error messages
 430+ *
 431+ * @params:
 432+ * $data array of user input
 433+ * $result string of name-value pair results returned by Payflow
 434+ *
 435+ * Credit:code modified from payflowpro_example_EC.php posted (and supervised) on the PayPal developers message board
 436+ */
 437+ private function getResults($data, $result) {
 438+ global $wgOut;
 439+
 440+ //prepare NVP response for sorting and outputting
 441+ $responseArray = array();
 442+
 443+ while(strlen($result)){
 444+ // name
 445+ $namepos= strpos($result,'=');
 446+ $nameval = substr($result,0,$namepos);
 447+ // value
 448+ $valuepos = strpos($result,'&') ? strpos($result,'&'): strlen($result);
 449+ $valueval = substr($result,$namepos+1,$valuepos-$namepos-1);
 450+ // decoding the respose
 451+ $responseArray[$nameval] = $valueval;
 452+ $result = substr($result,$valuepos+1,strlen($result));
 453+ }
 454+
 455+ // errors fall into three categories, "try again please", "sorry it didn't work out", and "approved"
 456+ // try again errors have not yet been developed
 457+ // they will most likely return false and the form is displayed again with the error message (counted)
 458+ // declines and approvals are displayed with data
 459+ $resultCode = $responseArray['RESULT'];
 460+ $responseMsg = "There was an problem processing the transaction. Please try again or contact us.";
 461+ $errorReturn = "0";
 462+
 463+
 464+ //declines and approval
 465+ if ($resultCode == '0') {
 466+ $responseMsg = "Your transaction has been approved. Thank you for your donation!";
 467+ $errorReturn = "1";
 468+ } else if ($resultCode == "12" ) {
 469+ $responseMsg = "Your transaction has been declined. Please contact your credit card company for further information.";
 470+ $errorReturn = "1";
 471+ } else if ($resultCode == '13') {
 472+ $responseMsg = "Voice authorization is required. Please contact us to continue the donation process.";
 473+ $errorReturn = "1";
 474+ }
 475+
 476+ //try again please
 477+
 478+ //Development of this functionality is pending testing on live test site and further clarification from Paypal
 479+ /*
 480+ if ($responseCode == '23' || $responseCode == '24') {
 481+ $responseMsg = "Your credit card number or expiration date is incorrect. Please try again.";
 482+ $errorReturn = "1";
 483+ } else if ()
 484+ */
 485+
 486+ $this->displayResults($data, $responseMsg);
 487+
 488+ }// end display results
 489+
 490+
 491+ /*
 492+ * Display response message to user with submitted user-supplied data
 493+ *
 494+ * @params
 495+ * $data array of posted data from form
 496+ * $responseMsg message supplied by getResults function
 497+ *
 498+ */
 499+ function displayResults($data, $responseMsg) {
 500+ global $wgOut;
 501+
 502+ require_once('includes/countryCodes.inc');
 503+
 504+ // display response message
 505+ $wgOut->addHTML('<h3 class="response_message">' . $responseMsg . "</h3>");
 506+
 507+ //translate country code into text
 508+ $countries = countryCodes();
 509+
 510+ // display user submitted info
 511+ $submittedUserInfo = '<div class="submitted_response"><table>
 512+ <tr>
 513+ <td><h5>Transaction Details:</h5></td>
 514+ </tr>
 515+ <tr>
 516+ <td>Amount: </td><td>'. $data['amount'] . '</td>
 517+ </tr>
 518+ <td>Email: </td><td>'. $data['email'] . '</td>
 519+ </tr>
 520+ <td>Name: </td><td>'. $data['fname'] . '</td>
 521+ <td>'. $data['mname'] . '</td>
 522+ <td>'. $data['lname'] . '</td>
 523+ </tr>
 524+ <td>Address: </td><td>'. $data['street'] . '</td>
 525+ <td>'. $data['city'] . '</td>
 526+ <td>'. $data['state'] . '</td>
 527+ <td>'. $data['zip'] . '</td>
 528+ <td>'. $countries[$data['country']] . '</td>
 529+ </tr>
 530+ </table>';
 531+
 532+ $wgOut->addHTML($submittedUserInfo);
 533+
 534+ }
 535+
 536+
 537+} // end class
Index: trunk/extensions/DonationInterface/payflowpro_gateway/includes/stateAbbreviations.inc
@@ -0,0 +1,64 @@
 2+<?php
 3+
 4+/*
 5+ * Supplies drop down menu options of US states
 6+ */
 7+function statesMenu() {
 8+ $states = '<option value="">Select a State</option>
 9+ <option value="XX">Outside the U.S.</option>
 10+ <option value="AK">Alaska</option>
 11+ <option value="AL">Alabama</option>
 12+ <option value="AR">Arkansas</option>
 13+ <option value="AZ">Arizona</option>
 14+ <option value="CA">California</option>
 15+ <option value="CO">Colorado</option>
 16+ <option value="CT">Connecticut</option>
 17+ <option value="DC">Washington D.C.</option>
 18+ <option value="DE">Delaware</option>
 19+ <option value="FL">Florida</option>
 20+ <option value="GA">Georgia</option>
 21+ <option value="HI">Hawaii</option>
 22+ <option value="IA">Iowa</option>
 23+ <option value="ID">Idaho</option>
 24+ <option value="IL">Illinois</option>
 25+ <option value="IN">Indiana</option>
 26+ <option value="KS">Kansas</option>
 27+ <option value="KY">Kentucky</option>
 28+ <option value="LA">Louisiana</option>
 29+ <option value="MA">Massachusetts</option>
 30+ <option value="MD">Maryland</option>
 31+ <option value="ME">Maine</option>
 32+ <option value="MI">Michigan</option>
 33+ <option value="MN">Minnesota</option>
 34+ <option value="MO">Missourri</option>
 35+ <option value="MS">Mississippi</option>
 36+ <option value="MT">Montana</option>
 37+ <option value="NC">North Carolina</option>
 38+ <option value="ND">North Dakota</option>
 39+ <option value="NE">Nebraska</option>
 40+ <option value="NH">New Hampshire</option>
 41+ <option value="NJ">New Jersey</option>
 42+ <option value="NM">New Mexico</option>
 43+ <option value="NV">Nevada</option>
 44+ <option value="NY">New York</option>
 45+ <option value="OH">Ohio</option>
 46+ <option value="OK">Oklahoma</option>
 47+ <option value="OR">Oregon</option>
 48+ <option value="PA">Pennsylvania</option>
 49+ <option value="PR">Puerto Rico</option>
 50+ <option value="RI">Rhode Island</option>
 51+ <option value="SC">South Carolina</option>
 52+ <option value="SD">South Dakota</option>
 53+ <option value="TN">Tennessee</option>
 54+ <option value="TX">Texas</option>
 55+ <option value="UT">Utah</option>
 56+ <option value="VA">Virginia</option>
 57+ <option value="VT">Vermont</option>
 58+ <option value="WA">Washington</option>
 59+ <option value="WI">Wisconsin</option>
 60+ <option value="WV">West Virginia</option>
 61+ <option value="WY">Wyoming</option>';
 62+
 63+ return $states;
 64+ }
 65+
Index: trunk/extensions/DonationInterface/payflowpro_gateway/includes/payflowUser.inc
@@ -0,0 +1,31 @@
 2+<?php
 3+
 4+/**
 5+* Payflow Pro account information
 6+* Payflow individual account information must be defined in the LocalSettings.php file
 7+*/
 8+function payflowUser() {
 9+ // User account information from LocalSettings.php
 10+ global $wgPayflowProPartnerID,
 11+ $wgPayflowProVendorID,
 12+ $wgPayflowProUserID,
 13+ $wgPayflowProPassword,
 14+ $wgPayflowProURL,
 15+ $wgPayflowProTestingURL;
 16+
 17+ $payflow_data = array(
 18+ 'partner' => $wgPayflowProPartnerID, //PayPal or original authorized reseller
 19+ 'vendor' => $wgPayflowProVendorID, // paypal merchant login ID
 20+ 'user' => $wgPayflowProUserID, //if one or more users are set up, authorized user ID, else same as VENDOR
 21+ 'password' => $wgPayflowProPassword, //merchant login password
 22+ 'paypalurl' => $wgPayflowProURL,
 23+ 'testingurl' => $wgPayflowProTestingURL, // Payflow testing URL
 24+ 'trxtype' => "S", //transaction type - all donations are a sale
 25+ 'tender' => "C", //credit card - all transactions in this case are credit cards
 26+ 'verbosity' => "MEDIUM", //level of detail in Payflow response
 27+ 'user_ip' => $_SERVER['REMOTE_ADDR'], //current user's ip address
 28+ 'order_id' => date('ymdH').rand(1000,9999), // Generate random order number
 29+ );
 30+
 31+ return $payflow_data;
 32+}
Index: trunk/extensions/DonationInterface/payflowpro_gateway/includes/countryCodes.inc
@@ -0,0 +1,256 @@
 2+<?php
 3+
 4+/*
 5+ * List of ISO numeric country codes to display as select menu to user
 6+ * needed to translate country to name-value pair 3-digit variable
 7+ */
 8+function countryCodes() {
 9+
 10+ $countryCode = array(
 11+ '840' => 'United States',
 12+ '124' => 'Canada',
 13+ '826' => 'United Kingdom',
 14+ '004' => 'Afghanistan',
 15+ '008' => 'Albania',
 16+ '012' => 'Algeria',
 17+ '016' => 'American Samoa',
 18+ '020' => 'Andorra',
 19+ '024' => 'Angola',
 20+ '660' => 'Anguilla',
 21+ '010' => 'Antarctica',
 22+ '028' => 'Antigua and Barbuda',
 23+ '032' => 'Argentina',
 24+ '051' => 'Armenia',
 25+ '533' => 'Aruba',
 26+ '036' => 'Australia',
 27+ '040' => 'Austria',
 28+ '031' => 'Azerbaijan',
 29+ '044' => 'Bahamas',
 30+ '048' => 'Bahrain',
 31+ '050' => 'Bangladesh',
 32+ '052' => 'Barbados',
 33+ '112' => 'Belarus',
 34+ '056' => 'Belgium',
 35+ '084' => 'Belize',
 36+ '204' => 'Benin',
 37+ '060' => 'Bermuda',
 38+ '064' => 'Bhutan',
 39+ '068' => 'Bolivia, Plurinational State of',
 40+ '070' => 'Bosnia and Herzegovina',
 41+ '072' => 'Botswana',
 42+ '074' => 'Bouvet Island',
 43+ '076' => 'Brazil',
 44+ '086' => 'British Indian Ocean Territory',
 45+ '096' => 'Brunei Darussalam',
 46+ '100' => 'Bulgaria',
 47+ '854' => 'Burkina Faso',
 48+ '108' => 'Burundi',
 49+ '116' => 'Cambodia',
 50+ '120' => 'Cameroon',
 51+ '124' => 'Canada',
 52+ '132' => 'Cape Verde',
 53+ '136' => 'Cayman Islands',
 54+ '140' => 'Central African Republic',
 55+ '148' => 'Chad',
 56+ '152' => 'Chile',
 57+ '156' => 'China',
 58+ '162' => 'Christmas Island',
 59+ '166' => 'Cocos (Keeling) Islands',
 60+ '017' => 'Colombia',
 61+ '174' => 'Comoros',
 62+ '178' => 'Congo',
 63+ '180' => 'Congo, the Democratic Republic of the',
 64+ '184' => 'Cook Islands',
 65+ '188' => 'Costa Rica',
 66+ '384' => "C&ocirc;te d'Ivoire",
 67+ '191' => 'Croatia (Hrvatska)',
 68+ '192' => 'Cuba',
 69+ '196' => 'Cyprus',
 70+ '203' => 'Czech Republic',
 71+ '208' => 'Denmark',
 72+ '262' => 'Djibouti',
 73+ '212' => 'Dominica',
 74+ '214' => 'Dominican Republic',
 75+ '626' => 'East Timor',
 76+ '218' => 'Ecuador',
 77+ '818' => 'Egypt',
 78+ '222' => 'El Salvador',
 79+ '226' => 'Equatorial Guinea',
 80+ '232' => 'Eritrea',
 81+ '233' => 'Estonia',
 82+ '231' => 'Ethiopia',
 83+ '238' => 'Falkland Islands (Malvinas)',
 84+ '234' => 'Faroe Islands',
 85+ '242' => 'Fiji',
 86+ '246' => 'Finland',
 87+ '250' => 'France',
 88+ '254' => 'French Guiana',
 89+ '258' => 'French Polynesia',
 90+ '260' => 'French Southern Territories',
 91+ '266' => 'Gabon',
 92+ '270' => 'Gambia',
 93+ '268' => 'Georgia',
 94+ '276' => 'Germany',
 95+ '288' => 'Ghana',
 96+ '292' => 'Gibraltar',
 97+ '300' => 'Greece',
 98+ '304' => 'Greenland',
 99+ '308' => 'Grenada',
 100+ '312' => 'Guadeloupe',
 101+ '316' => 'Guam',
 102+ '320' => 'Guatemala',
 103+ '324' => 'Guinea',
 104+ '624' => 'Guinea-Bissau',
 105+ '328' => 'Guyana',
 106+ '332' => 'Haiti',
 107+ '334' => 'Heard Island and McDonald Islands',
 108+ '340' => 'Honduras',
 109+ '344' => 'Hong Kong',
 110+ '348' => 'Hungary',
 111+ '352' => 'Iceland',
 112+ '356' => 'India',
 113+ '360' => 'Indonesia',
 114+ '364' => 'Iran, Islamic Republic of',
 115+ '368' => 'Iraq',
 116+ '372' => 'Ireland',
 117+ '376' => 'Israel',
 118+ '380' => 'Italy',
 119+ '388' => 'Jamaica',
 120+ '392' => 'Japan',
 121+ '400' => 'Jordan',
 122+ '398' => 'Kazakhstan',
 123+ '404' => 'Kenya',
 124+ '296' => 'Kiribati',
 125+ '408' => "Korea, Democratic People's Republic of",
 126+ '410' => 'Korea, Republic of',
 127+ '414' => 'Kuwait',
 128+ '417' => 'Kyrgyzstan',
 129+ '418' => 'Lao People\'s Democratic Republic',
 130+ '428' => 'Latvia',
 131+ '422' => 'Lebanon',
 132+ '426' => 'Lesotho',
 133+ '430' => 'Liberia',
 134+ '434' => 'Libyan Arab Jamahiriya',
 135+ '438' => 'Liechtenstein',
 136+ '440' => 'Lithuania',
 137+ '442' => 'Luxembourg',
 138+ '446' => 'Macao',
 139+ '807' => 'Macedonia, the former Yugoslav Republic of',
 140+ '450' => 'Madagascar',
 141+ '454' => 'Malawi',
 142+ '458' => 'Malaysia',
 143+ '462' => 'Maldives',
 144+ '466' => 'Mali',
 145+ '470' => 'Malta',
 146+ '584' => 'Marshall Islands',
 147+ '474' => 'Martinique',
 148+ '478' => 'Mauritania',
 149+ '480' => 'Mauritius',
 150+ '175' => 'Mayotte',
 151+ '484' => 'Mexico',
 152+ '583' => 'Micronesia, Federated States of',
 153+ '498' => 'Moldova, Republic of',
 154+ '492' => 'Monaco',
 155+ '496' => 'Mongolia',
 156+ '499' => 'Montenegro',
 157+ '500' => 'Montserrat',
 158+ '504' => 'Morocco',
 159+ '508' => 'Mozambique',
 160+ '104' => 'Myanmar',
 161+ '516' => 'Namibia',
 162+ '520' => 'Nauru',
 163+ '524' => 'Nepal',
 164+ '528' => 'Netherlands',
 165+ '530' => 'Netherlands Antilles',
 166+ '540' => 'New Caledonia',
 167+ '554' => 'New Zealand',
 168+ '558' => 'Nicaragua',
 169+ '562' => 'Niger',
 170+ '566' => 'Nigeria',
 171+ '570' => 'Niue',
 172+ '574' => 'Norfolk Island',
 173+ '580' => 'Northern Mariana Islands',
 174+ '578' => 'Norway',
 175+ '512' => 'Oman',
 176+ '586' => 'Pakistan',
 177+ '585' => 'Palau',
 178+ '591' => 'Panama',
 179+ '598' => 'Papua New Guinea',
 180+ '600' => 'Paraguay',
 181+ '604' => 'Peru',
 182+ '608' => 'Philippines',
 183+ '612' => 'Pitcairn',
 184+ '616' => 'Poland',
 185+ '620' => 'Portugal',
 186+ '630' => 'Puerto Rico',
 187+ '634' => 'Qatar',
 188+ '638' => 'R&eacute;union',
 189+ '642' => 'Romania',
 190+ '643' => 'Russian Federation',
 191+ '646' => 'Rwanda',
 192+ '659' => 'Saint Kitts and Nevis',
 193+ '662' => 'Saint Lucia',
 194+ '670' => 'Saint Vincent and the Grenadines',
 195+ '882' => 'Samoa',
 196+ '674' => 'San Marino',
 197+ '678' => 'Sao Tome and Principe',
 198+ '682' => 'Saudi Arabia',
 199+ '686' => 'Senegal',
 200+ '690' => 'Seychelles',
 201+ '694' => 'Sierra Leone',
 202+ '702' => 'Singapore',
 203+ '703' => 'Slovakia',
 204+ '705' => 'Slovenia',
 205+ '090' => 'Solomon Islands',
 206+ '706' => 'Somalia',
 207+ '710' => 'South Africa',
 208+ '239' => 'South Georgia and the South Sandwich Islands',
 209+ '724' => 'Spain',
 210+ '144' => 'Sri Lanka',
 211+ '654' => 'Saint Helena',
 212+ '666' => 'Saint Pierre and Miquelon',
 213+ '736' => 'Sudan',
 214+ '740' => 'Suriname',
 215+ '744' => 'Svalbard and Jan Mayen',
 216+ '748' => 'Swaziland',
 217+ '752' => 'Sweden',
 218+ '756' => 'Switzerland',
 219+ '760' => 'Syrian Arab Republic',
 220+ '762' => 'Tajikistan',
 221+ '834' => 'Tanzania, United Republic of',
 222+ '158' => 'Taiwan, Province of China',
 223+ '764' => 'Thailand',
 224+ '768' => 'Togo',
 225+ '772' => 'Tokelau',
 226+ '776' => 'Tonga',
 227+ '780' => 'Trinidad and Tobago',
 228+ '788' => 'Tunisia',
 229+ '792' => 'Turkey',
 230+ '795' => 'Turkmenistan',
 231+ '796' => 'Turks and Caicos Islands',
 232+ '798' => 'Tuvalu',
 233+ '800' => 'Uganda',
 234+ '804' => 'Ukraine',
 235+ '784' => 'United Arab Emirates',
 236+ '826' => 'United Kingdom',
 237+ '840' => 'United States',
 238+ '581' => 'United States Minor Outlying Islands',
 239+ '858' => 'Uruguay',
 240+ '860' => 'Uzbekistan',
 241+ '548' => 'Vanuatu',
 242+ '336' => 'Vatican City State',
 243+ '862' => 'Venezuela, Bolivarian Republic of',
 244+ '704' => 'Viet Nam',
 245+ '092' => 'Virgin Islands, British',
 246+ '850' => 'Virgin Islands, U.S.',
 247+ '876' => 'Wallis and Futuna',
 248+ '732' => 'Western Sahara',
 249+ '882' => 'Western Samoa',
 250+ '887' => 'Yemen',
 251+ '891' => 'Yugoslavia',
 252+ '894' => 'Zambia',
 253+ '716' => 'Zimbabwe'
 254+ );
 255+
 256+ return $countryCode;
 257+ }
Index: trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.i18n.php
@@ -0,0 +1,9 @@
 2+<?php
 3+$messages = array();
 4+
 5+$messages['en'] = array(
 6+ 'payflowprogateway' => 'Support Wikimedia',
 7+ 'greeting' => '<h3>Support Wikimedia</h3>',
 8+ 'form-message' => '<div id="mw-creditcard"><div class="mw-creditcard-intro"><p>Contribute with your credit card. (Other ways to give, including Paypal, check, or mail can be <a href="http://wikimediafoundation.org/wiki/Donate/WaysToGive/en"> found here</a>.)</p>
 9+ <p>To change amount or currency, return to <a href="https://www.mediawiki.org/index.php?title=Donate"> the donation page</a></p></div>'
 10+);
Index: trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.php
@@ -0,0 +1,86 @@
 2+<?php
 3+
 4+# Alert the user that this is not a valid entry point to MediaWiki if they try to access the special pages file directly.
 5+if (!defined('MEDIAWIKI')) {
 6+ echo <<<EOT
 7+To install my extension, put the following line in LocalSettings.php:
 8+require_once( "\$IP/extensions/payflowpro_gateway/payflowpro_gateway.php" );
 9+EOT;
 10+ exit( 1 );
 11+}
 12+
 13+$wgExtensionCredits['specialpage'][] = array(
 14+ 'name' => 'PayflowPro Gateway',
 15+ 'author' => 'Four Kitchens',
 16+ 'url' => 'http://www.mediawiki.org/wiki/Extension:PayflowProGateway',
 17+ 'description' => 'Integrates Paypal Payflow Pro credit card processing',
 18+ 'descriptionmsg' => 'payflowpro_gateway-desc',
 19+ 'version' => '1.0.0',
 20+);
 21+
 22+$dir = dirname(__FILE__) . '/';
 23+
 24+
 25+$wgAutoloadClasses['PayflowProGateway'] = $dir . 'payflowpro_gateway.body.php'; # Tell MediaWiki to load the extension body.
 26+$wgExtensionMessagesFiles['PayflowProGateway'] = $dir . 'payflowpro_gateway.i18n.php';
 27+$wgExtensionAliasesFiles['PayflowProGateway'] = $dir . 'payflowpro_gateway.alias.php';
 28+$wgSpecialPages['PayflowProGateway'] = 'PayflowProGateway'; # Let MediaWiki know about your new special page.
 29+
 30+
 31+/**
 32+* Hooks required to interface with the donation extension (include <donate> on page)
 33+*
 34+* gwValue supplies the value of the form option, the name that appears on the form
 35+* and the currencies supported by the gateway in the $values array
 36+*/
 37+$wgHooks['gwValue'][] = 'pfpGatewayValue';
 38+$wgHooks['gwPage'][] = 'pfpGatewayPage';
 39+
 40+/*
 41+* Hook to register form value and display name of this gateway
 42+* also supplies currencies supported by this gateway
 43+*/
 44+function pfpGatewayValue(&$values) {
 45+
 46+ $values['payflow'] = array(
 47+ 'gateway' => "payflow",
 48+ 'display_name' => "Credit Card",
 49+ 'form_value' => "payflow",
 50+ 'currencies' => array(
 51+ 'GBP' => "GBP: British Pound",
 52+ 'EUR' => "EUR: Euro",
 53+ 'USD' => "USD: U.S. Dollar",
 54+ 'AUD' => "AUD: Australian Dollar",
 55+ 'CAD' => "CAD: Canadian Dollar",
 56+ 'CHF' => "CHF: Swiss Franc",
 57+ 'CZK' => "CZK: Czech Koruna",
 58+ 'DKK' => "DKK: Danish Krone",
 59+ 'HKD' => "HKD: Hong Kong Dollar",
 60+ 'HUF' => "HUF: Hungarian Forint",
 61+ 'JPY' => "JPY: Japanese Yen",
 62+ 'NZD' => "NZD: New Zealand Dollar",
 63+ 'NOK' => "NOK: Norwegian Krone",
 64+ 'PLN' => "PLN: Polish Zloty",
 65+ 'SGD' => "SGD: Singapore Dollar",
 66+ 'SEK' => "SEK: Swedish Krona",
 67+ 'ILS' => "ILS: Isreali Shekel",
 68+ ),
 69+ );
 70+
 71+ return true;
 72+}
 73+
 74+/*
 75+* Hook to supply the page address of the payment gateway
 76+*
 77+* The user will redirected here with supplied data with input data appended (GET).
 78+* For example, if $url[$key] = index.php?title=Special:PayflowPro
 79+* the result might look like this: http://www.yourdomain.com/index.php?title=Special:PayflowPro&amount=75.00&currency_code=USD&payment_method=payflow
 80+*/
 81+function pfpGatewayPage(&$url) {
 82+ global $wgScript;
 83+
 84+ $url['payflow'] = $wgScript. "?title=Special:PayflowProGateway";
 85+
 86+ return true;
 87+}
\ No newline at end of file
Index: trunk/extensions/DonationInterface/paypal_gateway/paypal_gateway.il8n.php
@@ -0,0 +1,6 @@
 2+<?php
 3+$messages = array();
 4+
 5+$messages['en'] = array(
 6+ 'paypalgateway' => 'Paypal Gateway',
 7+);
\ No newline at end of file
Index: trunk/extensions/DonationInterface/paypal_gateway/paypal_gateway.php
@@ -0,0 +1,82 @@
 2+<?php
 3+# Alert the user that this is not a valid entry point to MediaWiki if they try to access the special pages file directly.
 4+if (!defined('MEDIAWIKI')) {
 5+ echo <<<EOT
 6+To install my extension, put the following line in LocalSettings.php:
 7+require_once( "\$IP/extensions/paypal_gateway/paypal_gateway.php" );
 8+EOT;
 9+ exit( 1 );
 10+}
 11+
 12+$wgExtensionCredits['specialpage'][] = array(
 13+ 'name' => 'Paypal Gateway',
 14+ 'author' => 'Four Kitchens',
 15+ 'url' => 'http://www.mediawiki.org/wiki/Extension:PaypalGateway',
 16+ 'description' => 'Registers paypal as a donation payment',
 17+ 'descriptionmsg' => 'paypal_gateway-desc',
 18+ 'version' => '1.0.0',
 19+);
 20+
 21+
 22+$dir = dirname(__FILE__) . '/';
 23+
 24+$wgExtensionMessagesFiles['PaypalGateway'] = $dir . 'paypal_gateway.il8n.php';
 25+
 26+/**
 27+* Hooks required to interface with the donation extension (include <donate> on page)
 28+*
 29+* gwValue supplies the value of the form option, the name that appears on the form
 30+* and the currencies supported by the gateway in the $values array
 31+*/
 32+$wgHooks['gwValue'][] = 'paypalGatewayValue';
 33+$wgHooks['gwPage'][] = 'paypalGatewayPage';
 34+
 35+/*
 36+* Hook to register form value and display name of this gateway
 37+* also supplies currencies supported by this gateway
 38+*/
 39+function paypalGatewayValue(&$values) {
 40+
 41+ $values['paypal'] = array(
 42+ 'gateway' => "paypal",
 43+ 'display_name' => "Paypal",
 44+ 'form_value' => "paypal",
 45+ 'currencies' => array(
 46+ 'GBP' => "GBP: British Pound",
 47+ 'EUR' => "EUR: Euro",
 48+ 'USD' => "USD: U.S. Dollar",
 49+ 'AUD' => "AUD: Australian Dollar",
 50+ 'CAD' => "CAD: Canadian Dollar",
 51+ 'CHF' => "CHF: Swiss Franc",
 52+ 'CZK' => "CZK: Czech Koruna",
 53+ 'DKK' => "DKK: Danish Krone",
 54+ 'HKD' => "HKD: Hong Kong Dollar",
 55+ 'HUF' => "HUF: Hungarian Forint",
 56+ 'JPY' => "JPY: Japanese Yen",
 57+ 'NZD' => "NZD: New Zealand Dollar",
 58+ 'NOK' => "NOK: Norwegian Krone",
 59+ 'PLN' => "PLN: Polish Zloty",
 60+ 'SGD' => "SGD: Singapore Dollar",
 61+ 'SEK' => "SEK: Swedish Krona",
 62+ 'ILS' => "ILS: Israeli Shekel",
 63+ ),
 64+ );
 65+
 66+ return true;
 67+}
 68+
 69+/*
 70+* Hook to supply the page address of the payment gateway
 71+*
 72+* The user will redirected here with amount and currency code appended (GET).
 73+* NOTE: $wgPaypalEmail is the business email associated with the Paypal account
 74+* It is set in the LocalSettings.php file
 75+*/
 76+function paypalGatewayPage(&$url) {
 77+ // Business email address set in LocalSettings.php
 78+ global $wgPaypalEmail;
 79+
 80+ $url['paypal'] = "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=". urlencode($wgPaypalEmail) ."&lc=US&no_note=1&no_shipping=1&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted";
 81+
 82+ return true;
 83+}
\ No newline at end of file
Index: trunk/extensions/DonationInterface/donate_interface/donate_interface.setup.php
@@ -0,0 +1,16 @@
 2+<?php
 3+
 4+# Alert the user that this is not a valid entry point to MediaWiki if they try to access the special pages file directly.
 5+if (!defined('MEDIAWIKI')) {
 6+ echo <<<EOT
 7+To install my extension, put the following line in LocalSettings.php:
 8+require_once( "\$IP/extensions/donate_interface/donate_interface.php" );
 9+EOT;
 10+ exit( 1 );
 11+}
 12+
 13+
 14+$dir = dirname(__FILE__) . '/';
 15+
 16+$wgAutoloadClasses['donate_interface'] = $dir . 'donate_interface.php'; # Tell MediaWiki to load the extension body.
 17+$wgExtensionMessagesFiles['donate_interface'] = $dir . 'donate_interface.i18n.php';
\ No newline at end of file
Index: trunk/extensions/DonationInterface/donate_interface/validate_donation.js
@@ -0,0 +1,53 @@
 2+//<![CDATA[
 3+function validateForm( form ) {
 4+
 5+ var minimums = {
 6+ 'USD' : 1,
 7+ 'GBP' : 1, // $1.26
 8+ 'EUR' : 1, // $1.26
 9+ 'AUD' : 2, // $1.35
 10+ 'CAD' : 1, // $0.84
 11+ 'CHF' : 1, // $0.85
 12+ 'CZK' : 20, // $1.03
 13+ 'DKK' : 5, // $0.85
 14+ 'HKD' : 10, // $1.29
 15+ 'HUF' : 200, // $0.97
 16+ 'JPY' : 100, // $1
 17+ 'NZD' : 2, // $1.18
 18+ 'NOK' : 10, // $1.44
 19+ 'PLN' : 5, // $1.78
 20+ 'SGD' : 2, // $1.35
 21+ 'SEK' : 10, // $1.28
 22+ };
 23+
 24+ var error = true;
 25+
 26+ // Get amount selection
 27+ var amount = null;
 28+ for ( var i = 0; i < form.amount.length; i++ ) {
 29+ if ( form.amount[i].checked ) {
 30+ amount = form.amount[i].value;
 31+ }
 32+ }
 33+ if ( form.amount2.value != "" ) {
 34+ amount = form.amount2.value;
 35+ }
 36+ // Check amount is a real number
 37+ error = ( amount == null || isNaN( amount ) || amount.value <= 0 );
 38+ if ( error ) {
 39+ alert( 'You must enter a valid amount.' );
 40+ }
 41+
 42+ // Check amount is at least the minimum
 43+ var currency = form.currency_code[form.currency_code.selectedIndex].value;
 44+ if ( typeof( minimums[currency] ) == 'undefined' ) {
 45+ minimums[currency] = 1;
 46+ }
 47+ if ( amount < minimums[currency] ) {
 48+ alert( 'You must contribute at least $1'.replace('$1', minimums[currency] + ' ' + currency ) );
 49+ error = true;
 50+ }
 51+
 52+ return !error;
 53+}
 54+//]]>
Index: trunk/extensions/DonationInterface/donate_interface/donate_interface.php
@@ -0,0 +1,146 @@
 2+<?php
 3+//Avoid unstubbing $wgParser on setHook() too early on modern (1.12+) MW versions, as per r35980
 4+if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) {
 5+ $wgHooks['ParserFirstCallInit'][] = 'efDonateSetup';
 6+} else { // Otherwise do things the old fashioned way
 7+ $wgExtensionFunctions[] = 'efDonateSetup';
 8+}
 9+
 10+/*
 11+* Create <donate /> tag to include landing page donation form
 12+*/
 13+function efDonateSetup(&$parser) {
 14+ global $wgParser, $wgOut, $wgRequest;
 15+
 16+ $parser->disableCache();
 17+
 18+ $wgParser->setHook( 'donate', 'efDonateRender' );
 19+
 20+
 21+ // if form has been submitted, assign data and redirect user to chosen payment gateway
 22+ if ($_POST['process'] == "_yes_") {
 23+ //find out which amount option was chosen for amount, redefined buttons or text box
 24+ if (isset($_POST['amount'])) {
 25+ $amount = number_format($wgRequest->getText('amount'), 2);
 26+ } else { $amount = number_format($wgRequest->getText('amount2'), 2, '.', ''); }
 27+
 28+ // create array of user input
 29+ $userInput = array (
 30+ 'currency' => $wgRequest->getText('currency_code'),
 31+ 'amount' => $amount,
 32+ 'payment_method' => $wgRequest->getText('payment_method')
 33+ );
 34+
 35+ // ask payment processor extensions for their URL/page title
 36+ wfRunHooks('gwPage', array(&$url));
 37+
 38+ // send user to correct page for payment
 39+ redirectToProcessorPage($userInput, $url);
 40+
 41+ }// end if form has been submitted
 42+
 43+ return true;
 44+}
 45+
 46+
 47+/*
 48+* Function called by the <donate> parser tag
 49+*
 50+* Outputs the donation landing page form which collects
 51+* the donation amount, currency and payment processor type.
 52+*
 53+*/
 54+function efDonateRender( $input, $args, &$parser) {
 55+ global $wgOut;
 56+
 57+ $parser->disableCache();
 58+
 59+ //add javascript validation to <head>
 60+ $parser->mOutput->addHeadItem('<script type="text/javascript" language="javascript" src="/extensions/donate_interface/validate_donation.js"></script>');
 61+
 62+ //display form to gather data from user
 63+ $output = createOutput();
 64+
 65+ return $output;
 66+}
 67+
 68+/*
 69+* Supplies the form to efDonateRender()
 70+*
 71+* Payment gateway options are created with the hook 'gwValue". Each potential payment
 72+* option supplies it's value and name for the form, as well as currencies it supports.
 73+*/
 74+function createOutput() {
 75+
 76+ //get payment method gateway value and name from each gateway and create menu of options
 77+ $values = '';
 78+ wfRunHooks('gwValue', array(&$values));
 79+
 80+ foreach($values as $current) {
 81+ $optionMenu .= '<option value='. $current['form_value'] . '>'. $current['display_name'] .'</option>';
 82+ }
 83+
 84+ //get available currencies
 85+ //NOTE: currently all available currencies are accepted by all developed gateways
 86+ //the next version will include gateway/currency checking
 87+ //and inform user of gateways that aren't an option for that currency
 88+ foreach($values as $key) {
 89+ $currencies = $key['currencies'];
 90+ }
 91+
 92+ foreach($currencies as $key => $value) {
 93+ $currencyMenu .= '<option value='. $key .'>'. $value .'</option>';
 94+ }
 95+
 96+ // form markup
 97+ $output ='<form method="post" action="" name="donate" onsubmit="return validateForm(this)">
 98+ <div>Please choose a payment method, amount, and currency. (Other ways to give, including check or mail, can be <a href="https://www.mediawiki.org/wiki/Donate/WaysToGive/en" title="Donate/WaysToGive/en">found here</a>.)</div>
 99+ <div>Donation Amount: </div>
 100+ <div id="amount_box">
 101+ <input type="hidden" name="title" value="Special:PayflowPro" />
 102+ <input type="radio" name="amount" id="input_amount_3" value="100" />
 103+ <label for="input_amount_3">$100</label>
 104+ <input type="radio" name="amount" id="input_amount_2" value="75" />
 105+ <label for="input_amount_2">$75</label>
 106+ <input type="radio" name="amount" id="input_amount_1" value="30" />
 107+ <label for="input_amount_1">$30</label>
 108+ <label for="input_amount_other">Other: </label> <input type="text" name="amount2" size="5" />
 109+ <!-- currency menu -->
 110+ <p>Select Currency</p>
 111+ <select name="currency_code" id="input_currency_code" size="1">
 112+ <option value="USD" selected="selected">USD: U.S. Dollar</option>
 113+ <option value="XXX">-------</option>
 114+ '. $currencyMenu .'
 115+ </select></div>
 116+ <div>Payment method:
 117+ <select name="payment_method" id="select_payment_method">
 118+ '.$optionMenu.'
 119+ </select></div>
 120+ <input type="hidden" name="process" value="_yes_" />
 121+ <br />
 122+ <input class="red-input-button" type="submit" value="DONATE"/>
 123+ </form>';
 124+
 125+ return $output;
 126+}
 127+
 128+
 129+/*
 130+* Redirects user to their chosen payment processor
 131+*
 132+* Includes the user's input passed as GET
 133+* $url for the gateway was supplied with the gwPage hook and the key
 134+* matches the form value (also supplied by the gateway)
 135+*/
 136+function redirectToProcessorPage($userInput, $url) {
 137+ global $wgOut;
 138+
 139+ $chosenGateway = $userInput['payment_method'];
 140+
 141+ $wgOut->redirect($url[$chosenGateway].'&amount='.$userInput['amount'].'&currency_code='.$userInput['currency']);
 142+
 143+}
 144+
 145+
 146+
 147+
Index: trunk/extensions/DonationInterface/donate_interface/donate_interface.il8n.php
@@ -0,0 +1,6 @@
 2+<?php
 3+$messages = array();
 4+
 5+$messages['en'] = array(
 6+ 'donate_interface' => 'Support Wikimedia',
 7+);
\ No newline at end of file

Status & tagging log