r98202 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r98201‎ | r98202 | r98203 >
Date:00:48, 27 September 2011
Author:khorn
Status:deferred (Comments)
Tags:fundraising 
Comment:
More refactoring work for the gateway adapters, mostly surrounding the special page itself.
Modified paths:
  • /branches/fundraising/extensions/DonationInterface/donationinterface.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/gateway_common/DonationData.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/gateway_common/GatewayForm.php (added) (history)
  • /branches/fundraising/extensions/DonationInterface/gateway_common/gateway.adapter.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect_gateway.body.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect_gateway.php (modified) (history)
  • /branches/fundraising/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.php (modified) (history)

Diff [purge]

Index: branches/fundraising/extensions/DonationInterface/donationinterface.php
@@ -58,6 +58,7 @@
5959
6060 $wgAutoloadClasses['DonationData'] = $donationinterface_dir . 'gateway_common/DonationData.php';
6161 $wgAutoloadClasses['GatewayAdapter'] = $donationinterface_dir . 'gateway_common/gateway.adapter.php';
 62+$wgAutoloadClasses['GatewayForm'] = $donationinterface_dir . 'gateway_common/GatewayForm.php';
6263
6364 //THE GATEWAYS WILL RESET THIS when they are instantiated. You can override it, but it won't stick around that way.
6465 $wgDonationInterfaceTest = false;
@@ -108,6 +109,12 @@
109110 'position' => 'top'
110111 ) + $wgResourceTemplate;
111112
 113+
 114+/**
 115+ * The URL to redirect a transaction to PayPal
 116+ */
 117+$wgDonationInterfacePaypalURL = '';
 118+
112119 function efDonationInterfaceUnitTests( &$files ) {
113120 $files[] = dirname( __FILE__ ) . '/tests/GatewayAdapterTest.php';
114121 $files[] = dirname( __FILE__ ) . '/tests/DonationDataTest.php';
Index: branches/fundraising/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.php
@@ -94,11 +94,6 @@
9595 $wgPayflowProGatewayHTTPProxy = '';
9696
9797 /**
98 - * The URL to redirect a transaction to PayPal
99 - */
100 -$wgPayflowProGatewayPaypalURL = '';
101 -
102 -/**
10398 * Set the max-age value for Squid
10499 *
105100 * If you have Squid enabled for caching, use this variable to configure
Index: branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect_gateway.php
@@ -36,6 +36,8 @@
3737 $wgGlobalCollectGatewayURL = 'https://ps.gcsip.nl/wdl/wdl';
3838 $wgGlobalCollectGatewayTestingURL = 'https://'; // GlobalCollect testing URL
3939
 40+$wgGlobalCollectGatewayCSSVersion = 1;
 41+
4042 $wgGlobalCollectGatewayMerchantID = ''; // GlobalCollect ID
4143 // a boolean to determine if we're in testing mode
4244 $wgGlobalCollectGatewayTest = FALSE;
Index: branches/fundraising/extensions/DonationInterface/globalcollect_gateway/globalcollect_gateway.body.php
@@ -1,49 +1,13 @@
22 <?php
33
4 -class GlobalCollectGateway extends UnlistedSpecialPage {
 4+class GlobalCollectGateway extends GatewayForm {
55
66 /**
7 - * Defines the action to take on a PFP transaction.
8 - *
9 - * Possible values include 'process', 'challenge',
10 - * 'review', 'reject'. These values can be set during
11 - * data processing validation, for instance.
12 - *
13 - * Hooks are exposed to handle the different actions.
14 - *
15 - * Defaults to 'process'.
16 - * @var string
17 - */
18 - public $action = 'process';
19 -
20 - /**
21 - * Holds the GlobalCollect response from a transaction
22 - * @var array
23 - */
24 - public $payflow_response = array( );
25 -
26 - /**
27 - * A container for the form class
28 - *
29 - * Used to loard the form object to display the CC form
30 - * @var object
31 - */
32 - public $form_class;
33 -
34 - /**
35 - * An array of form errors
36 - * @var array
37 - */
38 - public $errors = array( );
39 -
40 - /**
417 * Constructor - set up the new special page
428 */
439 public function __construct() {
44 - parent::__construct( 'GlobalCollectGateway' );
45 - $this->errors = $this->getPossibleErrors();
46 -
4710 $this->adapter = new GlobalCollectAdapter();
 11+ parent::__construct(); //the next layer up will know who we are.
4812 }
4913
5014 /**
@@ -52,35 +16,18 @@
5317 * @param $par Mixed: parameter passed to the page or null
5418 */
5519 public function execute( $par ) {
56 - global $wgRequest, $wgOut, $wgExtensionAssetsPath,
57 - $wgPayFlowProGatewayCSSVersion;
58 -
 20+ global $wgRequest, $wgOut, $wgExtensionAssetsPath;
 21+ $CSSVersion = $this->adapter->getGlobal( 'CSSVersion' );
 22+
5923 $wgOut->allowClickjacking();
6024
6125 $wgOut->addExtensionStyle(
6226 $wgExtensionAssetsPath . '/DonationInterface/gateway_forms/css/gateway.css?284' .
63 - $wgPayFlowProGatewayCSSVersion );
 27+ $CSSVersion );
6428
65 - $scriptVars = array(
66 - 'globalcollectGatewayErrorMsgJs' => wfMsg( 'payflowpro_gateway-error-msg-js' ),
67 - 'globalcollectGatewayErrorMsgEmail' => wfMsg( 'payflowpro_gateway-error-msg-email' ),
68 - 'globalcollectGatewayErrorMsgAmount' => wfMsg( 'payflowpro_gateway-error-msg-amount' ),
69 - 'globalcollectGatewayErrorMsgEmailAdd' => wfMsg( 'payflowpro_gateway-error-msg-emailAdd' ),
70 - 'globalcollectGatewayErrorMsgFname' => wfMsg( 'payflowpro_gateway-error-msg-fname' ),
71 - 'globalcollectGatewayErrorMsgLname' => wfMsg( 'payflowpro_gateway-error-msg-lname' ),
72 - 'globalcollectGatewayErrorMsgStreet' => wfMsg( 'payflowpro_gateway-error-msg-street' ),
73 - 'globalcollectGatewayErrorMsgCity' => wfMsg( 'payflowpro_gateway-error-msg-city' ),
74 - 'globalcollectGatewayErrorMsgState' => wfMsg( 'payflowpro_gateway-error-msg-state' ),
75 - 'globalcollectGatewayErrorMsgZip' => wfMsg( 'payflowpro_gateway-error-msg-zip' ),
76 - 'globalcollectGatewayErrorMsgCountry' => wfMsg( 'payflowpro_gateway-error-msg-country' ),
77 - 'globalcollectGatewayErrorMsgCardType' => wfMsg( 'payflowpro_gateway-error-msg-card_type' ),
78 - 'globalcollectGatewayErrorMsgCardNum' => wfMsg( 'payflowpro_gateway-error-msg-card_num' ),
79 - 'globalcollectGatewayErrorMsgExpiration' => wfMsg( 'payflowpro_gateway-error-msg-expiration' ),
80 - 'globalcollectGatewayErrorMsgCvv' => wfMsg( 'payflowpro_gateway-error-msg-cvv' ),
81 - 'globalcollectGatewayCVVExplain' => wfMsg( 'payflowpro_gateway-cvv-explain' ),
82 - );
 29+ $gateway_id = $this->adapter->getIdentifier();
8330
84 - $wgOut->addScript( Skin::makeVariablesScript( $scriptVars ) );
 31+ $this->addErrorMessageScript();
8532
8633 // Make the wiki logo not clickable.
8734 // @fixme can this be moved into the form generators?
@@ -95,6 +42,17 @@
9643
9744 $this->setHeaders();
9845
 46+ /**
 47+ * handle PayPal redirection
 48+ *
 49+ * if paypal redirection is enabled ($wgPayflowProGatewayPaypalURL must be defined)
 50+ * and the PaypalRedirect form value must be true
 51+ */
 52+ if ( $wgRequest->getText( 'PaypalRedirect', 0 ) ) {
 53+ $this->paypalRedirect();
 54+ return;
 55+ }
 56+
9957 //TODO: This is short-circuiting what I really want to do here.
10058 //so stop it.
10159 $data = $this->adapter->getDisplayData();
@@ -108,11 +66,11 @@
10967 // increase the count of attempts
11068 //++$data['numAttempt'];
11169 // Check form for errors
112 - $form_errors = $this->fnPayflowValidateForm( $data, $this->errors );
 70+ $form_errors = $this->fnValidateForm( $data, $this->errors );
11371
11472 // If there were errors, redisplay form, otherwise proceed to next step
11573 if ( $form_errors ) {
116 - $this->fnPayflowDisplayForm( $data, $this->errors );
 74+ $this->displayForm( $data, $this->errors );
11775 } else { // The submitted form data is valid, so process it
11876 // allow any external validators to have their way with the data
11977 $result = $this->adapter->do_transaction( 'INSERT_ORDERWITHPAYMENT' );
@@ -186,258 +144,18 @@
187145 $this->displayResultsForDebug( $result );
188146 }
189147 $this->adapter->log( "Not posted, or not processed. Showing the form for the first time." );
190 - $this->fnPayflowDisplayForm( $data, $this->errors );
 148+ $this->displayForm( $data, $this->errors );
191149 }
192150 } else {
193151 if ( !$this->adapter->isCache() ) {
194152 // if we're not caching, there's a token mismatch
195 - $this->errors['general']['token-mismatch'] = wfMsg( 'payflowpro_gateway-token-mismatch' );
 153+ $this->errors['general']['token-mismatch'] = wfMsg( $gateway_id . '_gateway-token-mismatch' );
196154 }
197 - $this->fnPayflowDisplayForm( $data, $this->errors );
 155+ $this->displayForm( $data, $this->errors );
198156 }
199157 }
200158
201 - function displayResultsForDebug( $results ) {
202 - global $wgOut;
203 - $wgOut->addHTML( $results['message'] );
204 -
205 - if ( !empty( $results['errors'] ) ) {
206 - $wgOut->addHTML( "<ul>" );
207 - foreach ( $results['errors'] as $code => $value ) {
208 - $wgOut->addHTML( "<li>Error $code: $value" );
209 - }
210 - $wgOut->addHTML( "</ul>" );
211 - }
212 -
213 - if ( !empty( $results['data'] ) ) {
214 - $wgOut->addHTML( "<ul>" );
215 - foreach ( $results['data'] as $key => $value ) {
216 - if ( is_array( $value ) ) {
217 - $wgOut->addHTML( "<li>$key:<ul>" );
218 - foreach ( $value as $key2 => $val2 ) {
219 - $wgOut->addHTML( "<li>$key2: $val2" );
220 - }
221 - $wgOut->addHTML( "</ul>" );
222 - } else {
223 - $wgOut->addHTML( "<li>$key: $value" );
224 - }
225 - }
226 - $wgOut->addHTML( "</ul>" );
227 - } else {
228 - $wgOut->addHTML( "Empty Results" );
229 - }
230 - if ( array_key_exists( 'Donor', $_SESSION ) ) {
231 - $wgOut->addHTML( "Session Donor Vars:<ul>" );
232 - foreach ( $_SESSION['Donor'] as $key => $val ) {
233 - $wgOut->addHTML( "<li>$key: $val" );
234 - }
235 - $wgOut->addHTML( "</ul>" );
236 - } else {
237 - $wgOut->addHTML( "No Session Donor Vars:<ul>" );
238 - }
239 - }
240 -
241159 /**
242 - * Build and display form to user
243 - *
244 - * @param $data Array: array of posted user input
245 - * @param $error Array: array of error messages returned by validate_form function
246 - *
247 - * The message at the top of the form can be edited in the payflow_gateway.i18n.php file
248 - */
249 - public function fnPayflowDisplayForm( &$data, &$error ) {
250 - global $wgOut, $wgRequest;
251 -
252 - // save contrib tracking id early to track abondonment
253 -// if ( !empty($data) && ( $data[ 'numAttempt' ] == '0' && ( !$wgRequest->getText( 'utm_source_id', false ) || $wgRequest->getText( '_nocache_' ) == 'true' ) ) ) {
254 -// $tracked = $this->fnPayflowSaveContributionTracking( $data );
255 -// if ( !$tracked ) {
256 -// $when = time();
257 -// self::log( $data[ 'order_id' ] . ' Unable to save data to the contribution_tracking table ' . $when );
258 -// }
259 -// }
260 -
261 - $form_class = $this->getFormClass();
262 - $form_obj = new $form_class( $data, $error, $this->adapter );
263 - $form = $form_obj->getForm();
264 - $wgOut->addHTML( $form );
265 - }
266 -
267 - /**
268 - * Set the form class to use to generate the CC form
269 - *
270 - * @param string $class_name The class name of the form to use
271 - */
272 - public function setFormClass( $class_name = NULL ) {
273 - if ( !$class_name ) {
274 - global $wgRequest, $wgPayflowProGatewayDefaultForm;
275 - $form_class = $wgRequest->getText( 'form_name', $wgPayflowProGatewayDefaultForm );
276 -
277 - // make sure our form class exists before going on, if not try loading default form class
278 - $class_name = "Gateway_Form_" . $form_class;
279 - if ( !class_exists( $class_name ) ) {
280 - $class_name_orig = $class_name;
281 - $class_name = "Gateway_Form_" . $wgPayflowProGatewayDefaultForm;
282 - if ( !class_exists( $class_name ) ) {
283 - throw new MWException( 'Could not load form ' . $class_name_orig . ' nor default form ' . $class_name );
284 - }
285 - }
286 - }
287 - $this->form_class = $class_name;
288 - }
289 -
290 - /**
291 - * Get the currently set form class
292 - *
293 - * Will set the form class if the form class not already set
294 - * Using logic in setFormClass()
295 - * @return string
296 - */
297 - public function getFormClass() {
298 - if ( !isset( $this->form_class ) ) {
299 - $this->setFormClass();
300 - }
301 - return $this->form_class;
302 - }
303 -
304 - /**
305 - * Checks posted form data for errors and returns array of messages
306 - */
307 - private function fnPayflowValidateForm( &$data, &$error ) {
308 - global $wgPayflowProGatewayPriceFloor, $wgPayflowProGatewayPriceCeiling;
309 -
310 - // begin with no errors
311 - $error_result = '0';
312 -
313 - // create the human-speak message for required fields
314 - // does not include fields that are not required
315 - $msg = array(
316 - 'amount' => wfMsg( 'payflowpro_gateway-error-msg-amount' ),
317 - 'emailAdd' => wfMsg( 'payflowpro_gateway-error-msg-emailAdd' ),
318 - 'fname' => wfMsg( 'payflowpro_gateway-error-msg-fname' ),
319 - 'lname' => wfMsg( 'payflowpro_gateway-error-msg-lname' ),
320 - 'street' => wfMsg( 'payflowpro_gateway-error-msg-street' ),
321 - 'city' => wfMsg( 'payflowpro_gateway-error-msg-city' ),
322 - 'state' => wfMsg( 'payflowpro_gateway-error-msg-state' ),
323 - 'zip' => wfMsg( 'payflowpro_gateway-error-msg-zip' ),
324 - 'card_num' => wfMsg( 'payflowpro_gateway-error-msg-card_num' ),
325 - 'expiration' => wfMsg( 'payflowpro_gateway-error-msg-expiration' ),
326 - 'cvv' => wfMsg( 'payflowpro_gateway-error-msg-cvv' ),
327 - );
328 -
329 - // find all empty fields and create message
330 - foreach ( $data as $key => $value ) {
331 - if ( $value == '' || ($key == 'state' && $value == 'YY' ) ) {
332 - // ignore fields that are not required
333 - if ( isset( $msg[$key] ) ) {
334 - $error[$key] = "**" . wfMsg( 'payflowpro_gateway-error-msg', $msg[$key] ) . "**<br />";
335 - $error_result = '1';
336 - }
337 - }
338 - }
339 -
340 - // check amount
341 - if ( !preg_match( '/^\d+(\.(\d+)?)?$/', $data['amount'] ) ||
342 - ( ( float ) $this->convert_to_usd( $data['currency'], $data['amount'] ) < ( float ) $wgPayflowProGatewayPriceFloor ||
343 - ( float ) $this->convert_to_usd( $data['currency'], $data['amount'] ) > ( float ) $wgPayflowProGatewayPriceCeiling ) ) {
344 - $error['invalidamount'] = wfMsg( 'payflowpro_gateway-error-msg-invalid-amount' );
345 - $error_result = '1';
346 - }
347 -
348 - // is email address valid?
349 - $isEmail = User::isValidEmailAddr( $data['email'] );
350 -
351 - // create error message (supercedes empty field message)
352 - if ( !$isEmail ) {
353 - $error['emailAdd'] = wfMsg( 'payflowpro_gateway-error-msg-email' );
354 - $error_result = '1';
355 - }
356 -
357 - // validate that credit card number entered is correct and set the card type
358 - if ( preg_match( '/^3[47][0-9]{13}$/', $data['card_num'] ) ) { // american express
359 - $data['card'] = 'american';
360 - } elseif ( preg_match( '/^5[1-5][0-9]{14}$/', $data['card_num'] ) ) { // mastercard
361 - $data['card'] = 'mastercard';
362 - } elseif ( preg_match( '/^4[0-9]{12}(?:[0-9]{3})?$/', $data['card_num'] ) ) {// visa
363 - $data['card'] = 'visa';
364 - } elseif ( preg_match( '/^6(?:011|5[0-9]{2})[0-9]{12}$/', $data['card_num'] ) ) { // discover
365 - $data['card'] = 'discover';
366 - } else { // an invalid credit card number was entered
367 - //TODO: Make sure this is uncommented when you commit for reals!
368 - //$error_result = '1';
369 - //$error[ 'card_num' ] = wfMsg( 'payflowpro_gateway-error-msg-card-num' );
370 - }
371 -
372 - return $error_result;
373 - }
374 -
375 - /**
376 - * "Reads" the name-value pair result string returned by Payflow and creates corresponding error messages
377 - *
378 - * @param $data Array: array of user input
379 - * @param $result String: name-value pair results returned by Payflow
380 - *
381 - * Credit: code modified from globalcollect_example_EC.php posted (and supervised) on the PayPal developers message board
382 - */
383 - private function fnPayflowGetResults( $data, $result ) {
384 - // prepare NVP response for sorting and outputting
385 - $responseArray = array( );
386 -
387 - /**
388 - * The result response string looks like:
389 - * RESULT=7&PNREF=E79P2C651DC2&RESPMSG=Field format error&HOSTCODE=10747&DUPLICATE=1
390 - * We want to turn this into an array of key value pairs, so explode on '&' and then
391 - * split up the resulting strings into $key => $value
392 - */
393 - $result_arr = explode( "&", $result );
394 - foreach ( $result_arr as $result_pair ) {
395 - list( $key, $value ) = preg_split( "/=/", $result_pair );
396 - $responseArray[$key] = $value;
397 - }
398 -
399 - // store the response array as an object property for easy retrival/manipulation elsewhere
400 - $this->payflow_response = $responseArray;
401 -
402 - // errors fall into three categories, "try again please", "sorry it didn't work out", and "approved"
403 - // get the result code for response array
404 - $resultCode = $responseArray['RESULT'];
405 -
406 - // initialize response message
407 - $responseMsg = '';
408 -
409 - // interpret result code, return
410 - // approved (1), denied (2), try again (3), general error (4)
411 - $errorCode = $this->fnPayflowGetResponseMsg( $resultCode, $responseMsg );
412 -
413 - // log that the transaction is essentially complete
414 - self::log( $data['order_id'] . " Transaction complete." );
415 -
416 - // if approved, display results and send transaction to the queue
417 - if ( $errorCode == '1' ) {
418 - self::log( $data['order_id'] . " " . $data['i_order_id'] . " Transaction approved.", 'globalcollect_gateway', LOG_DEBUG );
419 - $this->fnPayflowDisplayApprovedResults( $data, $responseArray, $responseMsg );
420 - // give user a second chance to enter incorrect data
421 - } elseif ( ( $errorCode == '3' ) && ( $data['numAttempt'] < '5' ) ) {
422 - self::log( $data['order_id'] . " " . $data['i_order_id'] . " Transaction unsuccessful (invalid info).", 'globalcollect_gateway', LOG_DEBUG );
423 - // pass responseMsg as an array key as required by displayForm
424 - $this->errors['retryMsg'] = $responseMsg;
425 - $this->fnPayflowDisplayForm( $data, $this->errors );
426 - // if declined or if user has already made two attempts, decline
427 - } elseif ( ( $errorCode == '2' ) || ( $data['numAttempt'] >= '3' ) ) {
428 - self::log( $data['order_id'] . " " . $data['i_order_id'] . " Transaction declined.", 'globalcollect_gateway', LOG_DEBUG );
429 - $this->fnPayflowDisplayDeclinedResults( $responseMsg );
430 - } elseif ( ( $errorCode == '4' ) ) {
431 - self::log( $data['order_id'] . " " . $data['i_order_id'] . " Transaction unsuccessful.", 'globalcollect_gateway', LOG_DEBUG );
432 - $this->fnPayflowDisplayOtherResults( $responseMsg );
433 - } elseif ( ( $errorCode == '5' ) ) {
434 - self::log( $data['order_id'] . " " . $data['i_order_id'] . " Transaction pending.", 'globalcollect_gateway', LOG_DEBUG );
435 - $this->fnPayflowDisplayPending( $data, $responseArray, $responseMsg );
436 - }
437 - }
438 -
439 -// end display results
440 -
441 - /**
442160 * Interpret response code, return
443161 * 1 if approved
444162 * 2 if declined
@@ -496,284 +214,35 @@
497215 return $errorCode;
498216 }
499217
500 - /**
501 - * Prepares the transactional message to be sent via Stomp to queueing service
502 - *
503 - * @param array $data
504 - * @param array $resposneArray
505 - * @param array $responseMsg
506 - * @return array
507 - */
508 - public function prepareStompTransaction( $data, $responseArray, $responseMsg ) {
509 - $transaction = array( );
510 -
511 - // include response message
512 - $transaction['response'] = $responseMsg;
513 -
514 - // include date
515 - $transaction['date'] = time();
516 -
517 - // put all data into one array
518 - $optout = $this->determineOptOut( $data );
519 - $data['anonymous'] = $optout['anonymous'];
520 - $data['optout'] = $optout['optout'];
521 -
522 - $transaction += array_merge( $data, $responseArray );
523 -
524 - return $transaction;
525 - }
526 -
527 - /**
528 - * Fetch an array of country abbrevs => country names
529 - */
530 - public static function getCountries() {
531 - require_once( 'includes/countryCodes.inc' );
532 - return countryCodes();
533 - }
534 -
535 - /**
536 - * Display response message to user with submitted user-supplied data
537 - *
538 - * @param $data Array: array of posted data from form
539 - * @param $responseMsg String: message supplied by getResults function
540 - */
541 - function fnPayflowDisplayApprovedResults( $data, $responseArray, $responseMsg ) {
542 - global $wgOut, $wgExternalThankYouPage;
543 -
544 - $transaction = $this->prepareStompTransaction( $data, $responseArray, $responseMsg );
545 -
546 - /**
547 - * hook to call stomp functions
548 - *
549 - * Sends transaction to Stomp-based queueing service,
550 - * eg ActiveMQ
551 - */
552 - wfRunHooks( 'gwStomp', array( $transaction ) );
553 -
554 - if ( $wgExternalThankYouPage ) {
555 - $wgOut->redirect( $wgExternalThankYouPage . "/" . $data['language'] );
556 - } else {
557 - // display response message
558 - $wgOut->addHTML( '<h3 class="response_message">' . $responseMsg . '</h3>' );
559 -
560 - // translate country code into text
561 - $countries = $this->getCountries();
562 -
563 - $rows = array(
564 - 'title' => array( wfMsg( 'payflowpro_gateway-post-transaction' ) ),
565 - 'amount' => array( wfMsg( 'globalcollect_gateway-donor-amount' ), $data['amount'] ),
566 - 'email' => array( wfMsg( 'globalcollect_gateway-donor-email' ), $data['email'] ),
567 - 'name' => array( wfMsg( 'globalcollect_gateway-donor-name' ), $data['fname'], $data['mname'], $data['lname'] ),
568 - 'address' => array( wfMsg( 'globalcollect_gateway-donor-address' ), $data['street'], $data['city'], $data['state'], $data['zip'], $countries[$data['country']] ),
569 - );
570 -
571 - // if we want to show the response
572 - $wgOut->addHTML( Xml::buildTable( $rows, array( 'class' => 'submitted-response' ) ) );
573 - }
574 - // unset edit token
575 - $this->fnPayflowUnsetEditToken();
576 - }
577 -
578 - /**
579 - * Display response message to user with submitted user-supplied data
580 - *
581 - * @param $responseMsg String: message supplied by getResults function
582 - */
583 - function fnPayflowDisplayDeclinedResults( $responseMsg ) {
 218+ //TODO: Remember why the heck I decided to leave this here...
 219+ //arguably, it's because it's slightly more "view" related, but... still, shouldn't you get stashed
 220+ //in the new GatewayForm class so we can override in chlidren if we feel like it? Odd.
 221+ function addErrorMessageScript() {
584222 global $wgOut;
 223+ $gateway_id = $this->adapter->getIdentifier();
585224
586 - // general decline message
587 - $declinedDefault = wfMsg( 'php-response-declined' );
588 -
589 - // display response message
590 - $wgOut->addHTML( '<h3 class="response_message">' . $declinedDefault . ' ' . $responseMsg . '</h3>' );
591 -
592 - // unset edit token
593 - $this->fnPayflowUnsetEditToken();
594 - }
595 -
596 - /**
597 - * Display response message when there is a system error unrelated to user's entry
598 - *
599 - * @param $responseMsg String: message supplied by getResults function
600 - */
601 - function fnPayflowDisplayOtherResults( $responseMsg ) {
602 - global $wgOut;
603 -
604 - // general decline message
605 - $declinedDefault = wfMsg( 'php-response-declined' );
606 -
607 - // display response message
608 - $wgOut->addHTML( '<h3 class="response_message">' . $declinedDefault . ' ' . $responseMsg . '</h3>' );
609 -
610 - // unset edit token
611 - $this->fnPayflowUnsetEditToken();
612 - }
613 -
614 - function fnPayflowDisplayPending( $data, $responseArray, $responseMsg ) {
615 - global $wgOut;
616 -
617 - $transaction = $this->prepareStompTransaction( $data, $responseArray, $responseMsg );
618 -
619 - // hook to call stomp functions
620 - wfRunHooks( 'gwPendingStomp', array( $transaction ) );
621 -
622 - $thankyou = wfMsg( 'globalcollect_gateway-thankyou' );
623 -
624 - // display response message
625 - $wgOut->addHTML( '<h2 class="response_message">' . $thankyou . '</h2>' );
626 - $wgOut->addHTML( '<p>' . $responseMsg );
627 -
628 - // unset edit token
629 - $this->fnPayflowUnsetEditToken();
630 - }
631 -
632 - public function getPossibleErrors() {
633 - return array(
634 - 'general' => '',
635 - 'retryMsg' => '',
636 - 'invalidamount' => '',
637 - 'card_num' => '',
638 - 'card_type' => '',
639 - 'cvv' => '',
640 - 'fname' => '',
641 - 'lname' => '',
642 - 'city' => '',
643 - 'country' => '',
644 - 'street' => '',
645 - 'state' => '',
646 - 'zip' => '',
647 - 'emailAdd' => '',
 225+ $scriptVars = array(
 226+ $gateway_id . 'GatewayErrorMsgJs' => wfMsg( $gateway_id . '_gateway-error-msg-js' ),
 227+ $gateway_id . 'GatewayErrorMsgEmail' => wfMsg( $gateway_id . '_gateway-error-msg-email' ),
 228+ $gateway_id . 'GatewayErrorMsgAmount' => wfMsg( $gateway_id . '_gateway-error-msg-amount' ),
 229+ $gateway_id . 'GatewayErrorMsgEmailAdd' => wfMsg( $gateway_id . '_gateway-error-msg-emailAdd' ),
 230+ $gateway_id . 'GatewayErrorMsgFname' => wfMsg( $gateway_id . '_gateway-error-msg-fname' ),
 231+ $gateway_id . 'GatewayErrorMsgLname' => wfMsg( $gateway_id . '_gateway-error-msg-lname' ),
 232+ $gateway_id . 'GatewayErrorMsgStreet' => wfMsg( $gateway_id . '_gateway-error-msg-street' ),
 233+ $gateway_id . 'GatewayErrorMsgCity' => wfMsg( $gateway_id . '_gateway-error-msg-city' ),
 234+ $gateway_id . 'GatewayErrorMsgState' => wfMsg( $gateway_id . '_gateway-error-msg-state' ),
 235+ $gateway_id . 'GatewayErrorMsgZip' => wfMsg( $gateway_id . '_gateway-error-msg-zip' ),
 236+ $gateway_id . 'GatewayErrorMsgCountry' => wfMsg( $gateway_id . '_gateway-error-msg-country' ),
 237+ $gateway_id . 'GatewayErrorMsgCardType' => wfMsg( $gateway_id . '_gateway-error-msg-card_type' ),
 238+ $gateway_id . 'GatewayErrorMsgCardNum' => wfMsg( $gateway_id . '_gateway-error-msg-card_num' ),
 239+ $gateway_id . 'GatewayErrorMsgExpiration' => wfMsg( $gateway_id . '_gateway-error-msg-expiration' ),
 240+ $gateway_id . 'GatewayErrorMsgCvv' => wfMsg( $gateway_id . '_gateway-error-msg-cvv' ),
 241+ $gateway_id . 'GatewayCVVExplain' => wfMsg( $gateway_id . '_gateway-cvv-explain' ),
648242 );
649 - }
650243
651 - /**
652 - * Handle redirection of form content to PayPal
653 - *
654 - * @fixme If we can update contrib tracking table in ContributionTracking
655 - * extension, we can probably get rid of this method and just submit the form
656 - * directly to the paypal URL, and have all processing handled by ContributionTracking
657 - * This would make this a lot less hack-ish
658 - */
659 - public function paypalRedirect( &$data ) {
660 - global $wgPayflowProGatewayPaypalURL, $wgOut;
661 -
662 - // if we don't have a URL enabled throw a graceful error to the user
663 - if ( !strlen( $wgPayflowProGatewayPaypalURL ) ) {
664 - $this->errors['general']['nopaypal'] = wfMsg( 'payflow_gateway-error-msg-nopaypal' );
665 - return;
666 - }
667 -
668 - // update the utm source to set the payment instrument to pp rather than cc
669 - $utm_source_parts = explode( ".", $data['utm_source'] );
670 - $utm_source_parts[2] = 'pp';
671 - $data['utm_source'] = implode( ".", $utm_source_parts );
672 - $data['gateway'] = 'paypal';
673 - $data['currency_code'] = $data['currency'];
674 - /**
675 - * update contribution tracking
676 - */
677 - $this->updateContributionTracking( $data, true );
678 -
679 - $wgPayflowProGatewayPaypalURL .= "/" . $data['language'] . "?gateway=paypal";
680 -
681 - // submit the data to the paypal redirect URL
682 - $wgOut->redirect( $wgPayflowProGatewayPaypalURL . '&' . http_build_query( $data ) );
 244+ $wgOut->addScript( Skin::makeVariablesScript( $scriptVars ) );
683245 }
684246
685 - public static function log( $msg, $identifier='globalcollect_gateway', $log_level=LOG_INFO ) {
686 - global $wgGlobalCollectGatewayUseSyslog;
687 -
688 - // if we're not using the syslog facility, use wfDebugLog
689 - if ( !$wgGlobalCollectGatewayUseSyslog ) {
690 - wfDebugLog( $identifier, $msg );
691 - return;
692 - }
693 -
694 - // otherwise, use syslogging
695 - openlog( $identifier, LOG_ODELAY, LOG_SYSLOG );
696 - syslog( $log_level, $msg );
697 - closelog();
698 - }
699 -
700 - /**
701 - * Convert an amount for a particular currency to an amount in USD
702 - *
703 - * This is grosley rudimentary and likely wildly inaccurate.
704 - * This mimicks the hard-coded values used by the WMF to convert currencies
705 - * for validatoin on the front-end on the first step landing pages of their
706 - * donation process - the idea being that we can get a close approximation
707 - * of converted currencies to ensure that contributors are not going above
708 - * or below the price ceiling/floor, even if they are using a non-US currency.
709 - *
710 - * In reality, this probably ought to use some sort of webservice to get real-time
711 - * conversion rates.
712 - *
713 - * @param $currency_code
714 - * @param $amount
715 - * @return unknown_type
716 - */
717 - public function convert_to_usd( $currency_code, $amount ) {
718 - switch ( strtoupper( $currency_code ) ) {
719 - case 'USD':
720 - $usd_amount = $amount / 1;
721 - break;
722 - case 'GBP':
723 - $usd_amount = $amount / 1;
724 - break;
725 - case 'EUR':
726 - $usd_amount = $amount / 1;
727 - break;
728 - case 'AUD':
729 - $usd_amount = $amount / 2;
730 - break;
731 - case 'CAD':
732 - $usd_amount = $amount / 1;
733 - break;
734 - case 'CHF':
735 - $usd_amount = $amount / 1;
736 - break;
737 - case 'CZK':
738 - $usd_amount = $amount / 20;
739 - break;
740 - case 'DKK':
741 - $usd_amount = $amount / 5;
742 - break;
743 - case 'HKD':
744 - $usd_amount = $amount / 10;
745 - break;
746 - case 'HUF':
747 - $usd_amount = $amount / 200;
748 - break;
749 - case 'JPY':
750 - $usd_amount = $amount / 100;
751 - break;
752 - case 'NZD':
753 - $usd_amount = $amount / 2;
754 - break;
755 - case 'NOK':
756 - $usd_amount = $amount / 10;
757 - break;
758 - case 'PLN':
759 - $usd_amount = $amount / 5;
760 - break;
761 - case 'SGD':
762 - $usd_amount = $amount / 2;
763 - break;
764 - case 'SEK':
765 - $usd_amount = $amount / 10;
766 - break;
767 - case 'ILS':
768 - $usd_amount = $amount / 5;
769 - break;
770 - default:
771 - $usd_amount = $amount;
772 - break;
773 - }
774 -
775 - return $usd_amount;
776 - }
777 -
778247 }
779248
780249 // end class
Index: branches/fundraising/extensions/DonationInterface/gateway_common/DonationData.php
@@ -628,7 +628,6 @@
629629 //Looks like two places: Either right before a paypal redirect (if that's still a thing) or
630630 //just prior to curling something up to some server somewhere.
631631 //I took care of the one just prior to curling.
632 - //TODO: Determine if that paypal redirect is still a thing or not.
633632 public function updateContributionTracking( $force = false ) {
634633 // ony update contrib tracking if we're coming from a single-step landing page
635634 // which we know with cc# in utm_source or if force=true or if contribution_tracking_id is not set
Index: branches/fundraising/extensions/DonationInterface/gateway_common/GatewayForm.php
@@ -0,0 +1,330 @@
 2+<?php
 3+
 4+class GatewayForm extends UnlistedSpecialPage {
 5+
 6+ /**
 7+ * Defines the action to take on a transaction.
 8+ *
 9+ * Possible values include 'process', 'challenge',
 10+ * 'review', 'reject'. These values can be set during
 11+ * data processing validation, for instance.
 12+ *
 13+ * Hooks are exposed to handle the different actions.
 14+ *
 15+ * Defaults to 'process'.
 16+ * @var string
 17+ */
 18+ public $action = 'process';
 19+
 20+ /**
 21+ * A container for the form class
 22+ *
 23+ * Used to loard the form object to display the CC form
 24+ * @var object
 25+ */
 26+ public $form_class;
 27+
 28+ /**
 29+ * An array of form errors
 30+ * @var array
 31+ */
 32+ public $errors = array( );
 33+
 34+ function __construct() {
 35+ $me = get_called_class();
 36+ parent::__construct( $me );
 37+ $this->errors = $this->getPossibleErrors();
 38+ }
 39+
 40+ /**
 41+ * Checks posted form data for errors and returns array of messages
 42+ */
 43+ protected function fnValidateForm( &$data, &$error ) {
 44+ // begin with no errors
 45+ $error_result = '0';
 46+
 47+ // create the human-speak message for required fields
 48+ // does not include fields that are not required
 49+ $gateway_identifier = $this->adapter->getIdentifier();
 50+ $msg = array(
 51+ 'amount' => wfMsg( $gateway_identifier . '_gateway-error-msg-amount' ),
 52+ 'emailAdd' => wfMsg( $gateway_identifier . '_gateway-error-msg-emailAdd' ),
 53+ 'fname' => wfMsg( $gateway_identifier . '_gateway-error-msg-fname' ),
 54+ 'lname' => wfMsg( $gateway_identifier . '_gateway-error-msg-lname' ),
 55+ 'street' => wfMsg( $gateway_identifier . '_gateway-error-msg-street' ),
 56+ 'city' => wfMsg( $gateway_identifier . '_gateway-error-msg-city' ),
 57+ 'state' => wfMsg( $gateway_identifier . '_gateway-error-msg-state' ),
 58+ 'zip' => wfMsg( $gateway_identifier . '_gateway-error-msg-zip' ),
 59+ 'card_num' => wfMsg( $gateway_identifier . '_gateway-error-msg-card_num' ),
 60+ 'expiration' => wfMsg( $gateway_identifier . '_gateway-error-msg-expiration' ),
 61+ 'cvv' => wfMsg( $gateway_identifier . '_gateway-error-msg-cvv' ),
 62+ );
 63+
 64+ // find all empty fields and create message
 65+ foreach ( $data as $key => $value ) {
 66+ if ( $value == '' || ($key == 'state' && $value == 'YY' ) ) {
 67+ // ignore fields that are not required
 68+ if ( isset( $msg[$key] ) ) {
 69+ $error[$key] = "**" . wfMsg( $gateway_identifier . '_gateway-error-msg', $msg[$key] ) . "**<br />";
 70+ $error_result = '1';
 71+ }
 72+ }
 73+ }
 74+
 75+ // check amount
 76+ $priceFloor = $this->adapter->getGlobal( 'PriceFloor' );
 77+ $priceCeiling = $this->adapter->getGlobal( 'PriceCeiling' );
 78+ if ( !preg_match( '/^\d+(\.(\d+)?)?$/', $data['amount'] ) ||
 79+ ( ( float ) $this->convert_to_usd( $data['currency'], $data['amount'] ) < ( float ) $priceFloor ||
 80+ ( float ) $this->convert_to_usd( $data['currency'], $data['amount'] ) > ( float ) $priceCeiling ) ) {
 81+ $error['invalidamount'] = wfMsg( $gateway_identifier . '_gateway-error-msg-invalid-amount' );
 82+ $error_result = '1';
 83+ }
 84+
 85+ // is email address valid?
 86+ $isEmail = User::isValidEmailAddr( $data['email'] );
 87+
 88+ // create error message (supercedes empty field message)
 89+ if ( !$isEmail ) {
 90+ $error['emailAdd'] = wfMsg( $gateway_identifier . '_gateway-error-msg-email' );
 91+ $error_result = '1';
 92+ }
 93+
 94+ // validate that credit card number entered is correct and set the card type
 95+ if ( preg_match( '/^3[47][0-9]{13}$/', $data['card_num'] ) ) { // american express
 96+ $data['card'] = 'american';
 97+ } elseif ( preg_match( '/^5[1-5][0-9]{14}$/', $data['card_num'] ) ) { // mastercard
 98+ $data['card'] = 'mastercard';
 99+ } elseif ( preg_match( '/^4[0-9]{12}(?:[0-9]{3})?$/', $data['card_num'] ) ) {// visa
 100+ $data['card'] = 'visa';
 101+ } elseif ( preg_match( '/^6(?:011|5[0-9]{2})[0-9]{12}$/', $data['card_num'] ) ) { // discover
 102+ $data['card'] = 'discover';
 103+ } else { // an invalid credit card number was entered
 104+ //TODO: Make sure this is uncommented when you commit for reals!
 105+ //$error_result = '1';
 106+ //$error[ 'card_num' ] = wfMsg( $gateway_identifier . '_gateway-error-msg-card-num' );
 107+ }
 108+
 109+ return $error_result;
 110+ }
 111+
 112+ /**
 113+ * Build and display form to user
 114+ *
 115+ * @param $data Array: array of posted user input
 116+ * @param $error Array: array of error messages returned by validate_form function
 117+ *
 118+ * The message at the top of the form can be edited in the payflow_gateway.i18n.php file
 119+ */
 120+ public function displayForm( &$data, &$error ) {
 121+ global $wgOut, $wgRequest;
 122+
 123+ $form_class = $this->getFormClass();
 124+ $form_obj = new $form_class( $data, $error, $this->adapter );
 125+ $form = $form_obj->getForm();
 126+ $wgOut->addHTML( $form );
 127+ }
 128+
 129+ /**
 130+ * Set the form class to use to generate the CC form
 131+ *
 132+ * @param string $class_name The class name of the form to use
 133+ */
 134+ public function setFormClass( $class_name = NULL ) {
 135+ if ( !$class_name ) {
 136+ global $wgRequest;
 137+ $defaultForm = $this->adapter->getGlobal( 'DefaultForm' );
 138+ $form_class = $wgRequest->getText( 'form_name', $defaultForm );
 139+
 140+ // make sure our form class exists before going on, if not try loading default form class
 141+ $class_name = "Gateway_Form_" . $form_class;
 142+ if ( !class_exists( $class_name ) ) {
 143+ $class_name_orig = $class_name;
 144+ $class_name = "Gateway_Form_" . $defaultForm;
 145+ if ( !class_exists( $class_name ) ) {
 146+ throw new MWException( 'Could not load form ' . $class_name_orig . ' nor default form ' . $class_name );
 147+ }
 148+ }
 149+ }
 150+ $this->form_class = $class_name;
 151+ }
 152+
 153+ /**
 154+ * Get the currently set form class
 155+ *
 156+ * Will set the form class if the form class not already set
 157+ * Using logic in setFormClass()
 158+ * @return string
 159+ */
 160+ public function getFormClass() {
 161+ if ( !isset( $this->form_class ) ) {
 162+ $this->setFormClass();
 163+ }
 164+ return $this->form_class;
 165+ }
 166+
 167+ function displayResultsForDebug( $results ) {
 168+ global $wgOut;
 169+ $wgOut->addHTML( $results['message'] );
 170+
 171+ if ( !empty( $results['errors'] ) ) {
 172+ $wgOut->addHTML( "<ul>" );
 173+ foreach ( $results['errors'] as $code => $value ) {
 174+ $wgOut->addHTML( "<li>Error $code: $value" );
 175+ }
 176+ $wgOut->addHTML( "</ul>" );
 177+ }
 178+
 179+ if ( !empty( $results['data'] ) ) {
 180+ $wgOut->addHTML( "<ul>" );
 181+ foreach ( $results['data'] as $key => $value ) {
 182+ if ( is_array( $value ) ) {
 183+ $wgOut->addHTML( "<li>$key:<ul>" );
 184+ foreach ( $value as $key2 => $val2 ) {
 185+ $wgOut->addHTML( "<li>$key2: $val2" );
 186+ }
 187+ $wgOut->addHTML( "</ul>" );
 188+ } else {
 189+ $wgOut->addHTML( "<li>$key: $value" );
 190+ }
 191+ }
 192+ $wgOut->addHTML( "</ul>" );
 193+ } else {
 194+ $wgOut->addHTML( "Empty Results" );
 195+ }
 196+ if ( array_key_exists( 'Donor', $_SESSION ) ) {
 197+ $wgOut->addHTML( "Session Donor Vars:<ul>" );
 198+ foreach ( $_SESSION['Donor'] as $key => $val ) {
 199+ $wgOut->addHTML( "<li>$key: $val" );
 200+ }
 201+ $wgOut->addHTML( "</ul>" );
 202+ } else {
 203+ $wgOut->addHTML( "No Session Donor Vars:<ul>" );
 204+ }
 205+ }
 206+
 207+ public function getPossibleErrors() {
 208+ return array(
 209+ 'general' => '',
 210+ 'retryMsg' => '',
 211+ 'invalidamount' => '',
 212+ 'card_num' => '',
 213+ 'card_type' => '',
 214+ 'cvv' => '',
 215+ 'fname' => '',
 216+ 'lname' => '',
 217+ 'city' => '',
 218+ 'country' => '',
 219+ 'street' => '',
 220+ 'state' => '',
 221+ 'zip' => '',
 222+ 'emailAdd' => '',
 223+ );
 224+ }
 225+
 226+ /**
 227+ * Convert an amount for a particular currency to an amount in USD
 228+ *
 229+ * This is grosley rudimentary and likely wildly inaccurate.
 230+ * This mimicks the hard-coded values used by the WMF to convert currencies
 231+ * for validatoin on the front-end on the first step landing pages of their
 232+ * donation process - the idea being that we can get a close approximation
 233+ * of converted currencies to ensure that contributors are not going above
 234+ * or below the price ceiling/floor, even if they are using a non-US currency.
 235+ *
 236+ * In reality, this probably ought to use some sort of webservice to get real-time
 237+ * conversion rates.
 238+ *
 239+ * @param $currency_code
 240+ * @param $amount
 241+ * @return unknown_type
 242+ */
 243+ public function convert_to_usd( $currency_code, $amount ) {
 244+ switch ( strtoupper( $currency_code ) ) {
 245+ case 'USD':
 246+ $usd_amount = $amount / 1;
 247+ break;
 248+ case 'GBP':
 249+ $usd_amount = $amount / 1;
 250+ break;
 251+ case 'EUR':
 252+ $usd_amount = $amount / 1;
 253+ break;
 254+ case 'AUD':
 255+ $usd_amount = $amount / 2;
 256+ break;
 257+ case 'CAD':
 258+ $usd_amount = $amount / 1;
 259+ break;
 260+ case 'CHF':
 261+ $usd_amount = $amount / 1;
 262+ break;
 263+ case 'CZK':
 264+ $usd_amount = $amount / 20;
 265+ break;
 266+ case 'DKK':
 267+ $usd_amount = $amount / 5;
 268+ break;
 269+ case 'HKD':
 270+ $usd_amount = $amount / 10;
 271+ break;
 272+ case 'HUF':
 273+ $usd_amount = $amount / 200;
 274+ break;
 275+ case 'JPY':
 276+ $usd_amount = $amount / 100;
 277+ break;
 278+ case 'NZD':
 279+ $usd_amount = $amount / 2;
 280+ break;
 281+ case 'NOK':
 282+ $usd_amount = $amount / 10;
 283+ break;
 284+ case 'PLN':
 285+ $usd_amount = $amount / 5;
 286+ break;
 287+ case 'SGD':
 288+ $usd_amount = $amount / 2;
 289+ break;
 290+ case 'SEK':
 291+ $usd_amount = $amount / 10;
 292+ break;
 293+ case 'ILS':
 294+ $usd_amount = $amount / 5;
 295+ break;
 296+ default:
 297+ $usd_amount = $amount;
 298+ break;
 299+ }
 300+
 301+ return $usd_amount;
 302+ }
 303+
 304+ public static function log( $msg, $log_level=LOG_INFO ) {
 305+ $this->adapter->log( $msg, $log_level );
 306+ }
 307+
 308+ /**
 309+ * Handle redirection of form content to PayPal
 310+ *
 311+ * @fixme If we can update contrib tracking table in ContributionTracking
 312+ * extension, we can probably get rid of this method and just submit the form
 313+ * directly to the paypal URL, and have all processing handled by ContributionTracking
 314+ * This would make this a lot less hack-ish
 315+ */
 316+ public function paypalRedirect() {
 317+ global $wgOut, $wgDonationInterfacePaypalURL;
 318+
 319+ // if we don't have a URL enabled throw a graceful error to the user
 320+ if ( !strlen( $wgDonationInterfacePaypalURL ) ) {
 321+ $gateway_identifier = $this->adapter->getIdentifier();
 322+ $this->errors['general']['nopaypal'] = wfMsg( $gateway_identifier . '_gateway-error-msg-nopaypal' );
 323+ return;
 324+ }
 325+ // submit the data to the paypal redirect URL
 326+ $wgOut->redirect( $this->adapter->getPaypalRedirectURL() );
 327+ }
 328+
 329+}
 330+
 331+//end of GatewayForm class definiton
\ No newline at end of file
Property changes on: branches/fundraising/extensions/DonationInterface/gateway_common/GatewayForm.php
___________________________________________________________________
Added: svn:eol-style
1332 + native
Index: branches/fundraising/extensions/DonationInterface/gateway_common/gateway.adapter.php
@@ -162,8 +162,12 @@
163163 return $this->dataObj->checkTokens();
164164 }
165165
166 - function getData() {
167 - return $this->postdata;
 166+ function getData( $val = '' ) {
 167+ if ( empty( $val ) ) {
 168+ return $this->postdata;
 169+ } else {
 170+ return $this->postdata[$val];
 171+ }
168172 }
169173
170174 function getDisplayData() {
@@ -726,4 +730,29 @@
727731 }
728732 }
729733
 734+ function getPaypalRedirectURL() {
 735+ global $wgDonationInterfacePaypalURL;
 736+
 737+ $utm_source = $this->getData( 'utm_source' );
 738+
 739+ // update the utm source to set the payment instrument to pp rather than cc
 740+ $utm_source_parts = explode( ".", $utm_source );
 741+ $utm_source_parts[2] = 'pp';
 742+ $data['utm_source'] = implode( ".", $utm_source_parts );
 743+ $data['gateway'] = 'paypal';
 744+ $data['currency_code'] = $data['currency'];
 745+
 746+ // Add our response vars to the data object.
 747+ $this->dataObj->addData( $data );
 748+ // refresh our data
 749+ $this->postdata = $this->dataObj->getData();
 750+
 751+ //update contribution tracking
 752+ $this->dataObj->updateContributionTracking( true );
 753+
 754+ $ret = $wgDonationInterfacePaypalURL . "/" . $this->postdata['language'] . "?gateway=paypal&" . http_build_query( $this->postdata );
 755+ self::log( $ret );
 756+ return $ret;
 757+ }
 758+
730759 }

Follow-up revisions

RevisionCommit summaryAuthorDate
r99606Only sends data paypal can process (that isn't null) on a paypal redirect....khorn00:18, 12 October 2011
r99613Escaping my debug-only output....khorn00:43, 12 October 2011
r100476follow-up to r98202 - some comments and fixeskaldari23:51, 21 October 2011
r100935Addresses a couple fixme-type comments from r98202.khorn01:51, 27 October 2011

Comments

#Comment by Awjrichards (talk | contribs)   22:08, 7 October 2011
+		global $wgRequest, $wgOut, $wgExtensionAssetsPath;
+		$CSSVersion = $this->adapter->getGlobal( 'CSSVersion' );
+
 		$wgOut->allowClickjacking();
 
 		$wgOut->addExtensionStyle(
 			$wgExtensionAssetsPath . '/DonationInterface/gateway_forms/css/gateway.css?284' .
-			$wgPayFlowProGatewayCSSVersion );
+			$CSSVersion );

This should be converted to rely on ResourceLoader, then we wont need to futz with $CSSVersion.

$wgOut->addScript( Skin::makeVariablesScript( $scriptVars ) );

Also should be converted to use ResourceLoader.

+		$ret = $wgDonationInterfacePaypalURL . "/" . $this->postdata['language'] . "?gateway=paypal&" . http_build_query( $this->postdata );

If I'm not mistaken, this is sending the entire data object to PayPal. We should probably only send the necessary fields/values.

When displaying output, like in displayResultsForDebug(), it is best to rely on MW's HTML or XML class for formatting - this will ensure proper escaping of values. (see http://www.mediawiki.org/wiki/Security_for_developers#Output_.28API.2C_CSS.2C_JavaScript.2C_HTML.2C_XML.2C_etc..29)

#Comment by Khorn (WMF) (talk | contribs)   00:45, 12 October 2011

Point 1: Resource Loaderification. This will have to get dealt with as part of the merge back into trunk (see revision r99077). In order to accomplish this, among many other things, the validate.input.js file will have to be moved to a gateway-agnostic location (probably the gateway_forms directory makes the most sense), and the resource module definitions will need to move to donationinterface.php, as the payflowpro_gateway.php file no longer exists.

Point 2: ...Ah, I think I see what's going on here: It looks like this was partially dealt with in trunk (same commit: r99077) with the form_placeholders.js now coming in through ResourceLoader. However, it looks like there's still some moderate lifting to be done there: If I'm reading all this correctly, that means all the messages previously defined in addErrorMessageScript need to be moved out of there, and instead loaded into the placeholders module as messages. As this is at least partially dependent on a change made in trunk after the initial branching, I'm inclined to tag that work as also being part of the merge process...

Point 3: fixed in r99606

Point 4: fixed in r99613

#Comment by Kaldari (talk | contribs)   23:30, 21 October 2011

+ if ( empty( $val ) ) {

Don't you want... if ( !$val ) { ...or... if ( $val === ) { ...instead?

We don't usually use empty() unless we really need to suppress errors for some reason. Otherwise ! is functionally equivalent (even for 0 values).

#Comment by Kaldari (talk | contribs)   23:33, 21 October 2011

Erg, that got munged:

Don't you want...
if ( !$val ) {
...or...
if ( $val === '' ) {
...instead?

#Comment by Khorn (WMF) (talk | contribs)   01:52, 27 October 2011

fixed in r100935

#Comment by Kaldari (talk | contribs)   23:47, 21 October 2011

Don't use class_exists(). It causes problems under HipHop). Use MWInit::classExists() instead.

#Comment by Kaldari (talk | contribs)   23:51, 21 October 2011

I fixed this issue in r100476.

#Comment by Kaldari (talk | contribs)   23:55, 21 October 2011

All

  • s have to be closed to be valid XHTML.
  • #Comment by Kaldari (talk | contribs)   23:56, 21 October 2011

    Arggh, munged again!

    All <li>s have to be closed to be valid XHTML.

    #Comment by Khorn (WMF) (talk | contribs)   01:52, 27 October 2011

    fixed in r100935

    #Comment by Kaldari (talk | contribs)   00:00, 22 October 2011

    + if ( !strlen( $wgDonationInterfacePaypalURL ) ) {

    !$wgDonationInterfacePaypalURL will give you the same result (except in the case that $wgDonationInterfacePaypalURL is set to 0, but that seems quite unlikely).

    OK, I think that's everything!

    #Comment by Khorn (WMF) (talk | contribs)   01:53, 27 October 2011

    By the time I got to trying to fix this in r100935, it was already gone. :)

    Status & tagging log