Index: trunk/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.body.php |
— | — | @@ -17,6 +17,12 @@ |
18 | 18 | public $action = NULL; |
19 | 19 | |
20 | 20 | /** |
| 21 | + * Holds the information from a Payflow transaction |
| 22 | + * @var array |
| 23 | + */ |
| 24 | + public $payflow_transaction = NULL; |
| 25 | + |
| 26 | + /** |
21 | 27 | * Constructor - set up the new special page |
22 | 28 | */ |
23 | 29 | public function __construct() { |
— | — | @@ -94,6 +100,8 @@ |
95 | 101 | 'optout' => '', |
96 | 102 | 'token' => $token, |
97 | 103 | 'contribution_tracking_id' => '', |
| 104 | + 'data_hash' => '', |
| 105 | + 'action' => '', |
98 | 106 | ); |
99 | 107 | |
100 | 108 | $error[] = ''; |
— | — | @@ -112,7 +120,6 @@ |
113 | 121 | |
114 | 122 | // track the number of attempts the user has made |
115 | 123 | $numAttempt = ( $wgRequest->getText( 'numAttempt' ) == '' ) ? '0' : $wgRequest->getText( 'numAttempt' ); |
116 | | - |
117 | 124 | // Populate from data |
118 | 125 | $data = array( |
119 | 126 | 'amount' => $amount, |
— | — | @@ -131,7 +138,7 @@ |
132 | 139 | 'cvv' => $wgRequest->getText( 'cvv' ), |
133 | 140 | 'currency' => $wgRequest->getText( 'currency_code' ), |
134 | 141 | 'payment_method' => $wgRequest->getText( 'payment_method' ), |
135 | | - 'order_id' => null, //will be set with $payflow_data |
| 142 | + 'order_id' => $wgRequest->getText( 'orderid' ), //will be set with $payflow_data |
136 | 143 | 'numAttempt' => $numAttempt, |
137 | 144 | 'referrer' => $wgRequest->getText( 'referrer' ), |
138 | 145 | 'utm_source' => $wgRequest->getText( 'utm_source' ), |
— | — | @@ -143,6 +150,8 @@ |
144 | 151 | 'optout' => $wgRequest->getText( 'email' ), |
145 | 152 | 'test_string' => $wgRequest->getText( 'process' ), //for showing payflow string during testing |
146 | 153 | 'contribution_tracking_id' => $wgRequest->getText( 'contribution_tracking_id' ), |
| 154 | + 'data_hash' => $wgRequest->getText( 'data_hash' ), |
| 155 | + 'action' => $wgRequest->getText( 'action' ), |
147 | 156 | ); |
148 | 157 | |
149 | 158 | // Get array of default account values necessary for Payflow |
— | — | @@ -151,7 +160,7 @@ |
152 | 161 | $payflow_data = payflowUser(); |
153 | 162 | |
154 | 163 | // assign this order ID to the $data array as well |
155 | | - $data['order_id'] = $payflow_data['order_id']; |
| 164 | + if ( strlen( $data['order_id'] ) < 1 ) $data['order_id'] = $payflow_data['order_id']; |
156 | 165 | |
157 | 166 | // Check form for errors and display |
158 | 167 | // match token |
— | — | @@ -171,31 +180,34 @@ |
172 | 181 | wfRunHooks( 'PayflowGatewayValidate', array( &$this, &$data )); |
173 | 182 | |
174 | 183 | // if the transaction was flagged for review |
175 | | - if ( in_array( 'review', $this->actions )) { |
| 184 | + if ( $this->action == 'review' ) { |
176 | 185 | // expose a hook for external handling of trxns flagged for review |
177 | | - wfRunHooks( 'PayflowGatewayReview', array( &$this, $data )); |
| 186 | + wfRunHooks( 'PayflowGatewayReview', array( &$this, &$data )); |
178 | 187 | } |
179 | 188 | |
180 | 189 | // if the transaction was flagged to be 'challenged' |
181 | | - if ( in_array( 'challenge', $this->actions )) { |
| 190 | + if ( $this->action == 'challenge' ) { |
182 | 191 | // expose a hook for external handling of trxns flagged for challenge (eg captcha) |
183 | | - wfRunHooks( 'PayflowGatewayChallenge', array( &$this, $data )); |
| 192 | + wfRunHooks( 'PayflowGatewayChallenge', array( &$this, &$data )); |
184 | 193 | } |
185 | 194 | |
186 | 195 | // if the transaction was flagged for rejection |
187 | | - if ( in_array( 'reject', $this->actions )) { |
| 196 | + if ( $this->action == 'reject' ) { |
188 | 197 | // expose a hook for external handling of trxns flagged for rejection |
189 | | - wfRunHooks( 'PayflowGatewayReject', array( &$this, $data )); |
| 198 | + wfRunHooks( 'PayflowGatewayReject', array( &$this, &$data )); |
190 | 199 | |
191 | 200 | $this->fnPayflowDisplayDeclinedResults( '' ); |
192 | 201 | } |
193 | 202 | |
194 | 203 | // if the transaction was flagged for processing |
195 | | - if ( in_array( 'process', $this->actions )) { |
| 204 | + if ( $this->action == 'process' ) { |
196 | 205 | // expose a hook for external handling of trxns ready for processing |
197 | | - wfRunHooks( 'PayflowGatewayProcess', array( &$this, $data )); |
| 206 | + wfRunHooks( 'PayflowGatewayProcess', array( &$this, &$data )); |
198 | 207 | $this->fnPayflowProcessTransaction( $data, $payflow_data ); |
199 | 208 | } |
| 209 | + |
| 210 | + // expose a hook for any post processing |
| 211 | + wfRunHooks( 'PayflowGatewayPostProcess', array( &$this, &$data )); |
200 | 212 | } |
201 | 213 | } else { |
202 | 214 | //Display form for the first time |
— | — | @@ -205,14 +217,14 @@ |
206 | 218 | } |
207 | 219 | |
208 | 220 | /** |
209 | | - * Displays form to user |
| 221 | + * Build the submission form sans submit button |
210 | 222 | * |
211 | | - * @param $data Array: array of posted user input |
212 | | - * @param $error Array: array of error messages returned by validate_form function |
213 | | - * |
214 | | - * The message at the top of the form can be edited in the payflow_gateway.i18.php file |
| 223 | + * This allows for additional form elements/processing to be handled |
| 224 | + * by extra modules (eg during 'challenge' action) |
| 225 | + * |
| 226 | + * See $this->fnPayflowDisplayForm |
215 | 227 | */ |
216 | | - private function fnPayflowDisplayForm( $data, &$error ) { |
| 228 | + public function fnPayflowGenerateFormBody( $data, &$error ) { |
217 | 229 | require_once( 'includes/stateAbbreviations.inc' ); |
218 | 230 | require_once( 'includes/countryCodes.inc' ); |
219 | 231 | |
— | — | @@ -428,10 +440,19 @@ |
429 | 441 | Xml::hidden( 'token', $data['token'] ) . |
430 | 442 | Xml::hidden( 'orderid', $data['order_id'] ) . |
431 | 443 | Xml::hidden( 'numAttempt', $data['numAttempt'] ) . |
432 | | - Xml::hidden( 'contribution_tracking_id', $data['contribution_tracking_id'] ); |
433 | | - |
| 444 | + Xml::hidden( 'contribution_tracking_id', $data['contribution_tracking_id'] ) . |
| 445 | + Xml::hidden( 'data_hash', $data[ 'data_hash' ] ) . |
| 446 | + Xml::hidden( 'action', $data[ 'action' ] ); |
| 447 | + return $form; |
| 448 | + } |
| 449 | + |
| 450 | + /** |
| 451 | + * Build the submit portion of the submission form |
| 452 | + * See $this->fnPayflowDiplayForm |
| 453 | + */ |
| 454 | + public function fnPayflowGenerateFormSubmit( $data, &$error ) { |
434 | 455 | // submit button and close form |
435 | | - $form .= Xml::openElement( 'div', array( 'class' => 'mw-donate-submessage' ) ) . |
| 456 | + $form = Xml::openElement( 'div', array( 'class' => 'mw-donate-submessage' ) ) . |
436 | 457 | wfMsg( 'payflowpro_gateway-donate-click' ) . |
437 | 458 | Xml::tags( 'div', array( 'id' => 'mw-donate-submit-button' ), |
438 | 459 | Xml::submitButton( wfMsg( 'payflowpro_gateway-submit-button' ) ) ) . |
— | — | @@ -442,7 +463,21 @@ |
443 | 464 | Xml::closeElement( 'form' ) . |
444 | 465 | Xml::closeElement( 'div' ) . |
445 | 466 | Xml::closeElement( 'div' ); |
| 467 | + return $form; |
| 468 | + } |
446 | 469 | |
| 470 | + /** |
| 471 | + * Build and displays form to user |
| 472 | + * |
| 473 | + * @param $data Array: array of posted user input |
| 474 | + * @param $error Array: array of error messages returned by validate_form function |
| 475 | + * |
| 476 | + * The message at the top of the form can be edited in the payflow_gateway.i18.php file |
| 477 | + */ |
| 478 | + public function fnPayflowDisplayForm( $data, &$error ) { |
| 479 | + global $wgOut; |
| 480 | + $form = $this->fnpayflowGenerateFormBody( &$data, &$error ); |
| 481 | + $form .= $this->fnPayflowGenerateFormSubmit( &$data, &$error ); |
447 | 482 | $wgOut->addHTML( $form ); |
448 | 483 | } |
449 | 484 | |
— | — | @@ -581,7 +616,7 @@ |
582 | 617 | 'LASTNAME' => $data['lname'], |
583 | 618 | 'STREET' => $data['street'], |
584 | 619 | 'ZIP' => $data['zip'], |
585 | | - 'INVNUM' => $payflow_data['order_id'], |
| 620 | + 'INVNUM' => $data['order_id'], |
586 | 621 | 'CVV2' => $data['cvv'], |
587 | 622 | 'CURRENCY' => $data['currency'], |
588 | 623 | 'VERBOSITY' => $payflow_data['verbosity'], |
— | — | @@ -601,7 +636,7 @@ |
602 | 637 | $headers[] = 'Content-Type: text/namevalue'; |
603 | 638 | $headers[] = 'Content-Length : ' . strlen( $payflow_query ); |
604 | 639 | $headers[] = 'X-VPS-Client-Timeout: 45'; |
605 | | - $headers[] = 'X-VPS-Request-ID:' . $payflow_data['order_id']; |
| 640 | + $headers[] = 'X-VPS-Request-ID:' . $data['order_id']; |
606 | 641 | $ch = curl_init(); |
607 | 642 | $paypalPostTo = isset ( $wgDonationTestingMode ) ? 'testingurl' : 'paypalurl'; |
608 | 643 | curl_setopt( $ch, CURLOPT_URL, $payflow_data[ $paypalPostTo ] ); |
— | — | @@ -794,6 +829,9 @@ |
795 | 830 | // hook to call stomp functions |
796 | 831 | wfRunHooks( 'gwStomp', array( &$transaction ) ); |
797 | 832 | |
| 833 | + // set the object property for the transaction |
| 834 | + $this->payflow_transaction = $transaction; |
| 835 | + |
798 | 836 | if ( $wgExternalThankYouPage ) { |
799 | 837 | $wgOut->redirect( $wgExternalThankYouPage . "/" . $data['language'] ); |
800 | 838 | } else { |
Index: trunk/extensions/DonationInterface/payflowpro_gateway/extras/minfraud/tests/minfraudTest.php |
— | — | @@ -4,7 +4,8 @@ |
5 | 5 | class minfraudTest extends PHPUnit_Framework_TestCase |
6 | 6 | { |
7 | 7 | protected function setUp() { |
8 | | - require_once( __FILE__ . '/../../minfraud.php'); |
| 8 | + $dir = dirname( __FILE__ ) . '/'; |
| 9 | + require_once( $dir . '../minfraud.php'); |
9 | 10 | global $wgMinFraudLog; |
10 | 11 | $wgMinFraudLog = dirname(__FILE__) . "/test_log"; |
11 | 12 | $license_key = 'XBCKSF4gnHA7'; |
— | — | @@ -149,9 +150,9 @@ |
150 | 151 | |
151 | 152 | public function testLogging() { |
152 | 153 | global $wgMinFraudLog; |
153 | | - $this->fixture->log( "foo" ); |
| 154 | + $this->fixture->log( '', '', "\"foo\"" ); |
154 | 155 | $new_fh = fopen( $wgMinFraudLog, 'r' ); |
155 | | - $this->assertEquals("foo\n", fread( $new_fh, filesize( $wgMinFraudLog ) )); |
| 156 | + $this->assertEquals('"'.date('c').'"'."\t\"\"\t\"\"\t\"foo\"\n", fread( $new_fh, filesize( $wgMinFraudLog ) )); |
156 | 157 | fclose( $new_fh ); |
157 | 158 | } |
158 | 159 | |
— | — | @@ -173,12 +174,12 @@ |
174 | 175 | $wgMinFraudSalt = 'salt'; |
175 | 176 | $data = array( |
176 | 177 | 'action' => '4bd7857c851039d1e07a434800fe752c6bd99aec61c325aef460441be1b95c3ab5236e43c8d06f41d77715dbd3cf94e679b86422ec3204f00ad433501e5005e9', |
177 | | - 'data_hash' => '8a42092df24db59b67ab2c6408e00553de93e79dc0d77467f5b91501a392cff99922a0b24f9d0cc5853ae874bbc79c20eb22814ce3a912d743d4137b1f795ac3', |
| 178 | + 'data_hash' => '029ef6f5c2a165215b5a92ff1a194e4a6de8c668d6193582da42713f119c1b07d8358b5cd94a3bd51c9aa50709c8533295215ce3cce8c2b61e69078d789bc3f3', |
178 | 179 | 'foo' |
179 | 180 | ); |
180 | 181 | $this->assertTrue( $this->fixture->bypass_minfraud( &$this->fixture, &$data )); |
181 | 182 | $this->assertEquals( 'challenge', $this->fixture->action ); |
182 | | - $this->assertEquals( '8a42092df24db59b67ab2c6408e00553de93e79dc0d77467f5b91501a392cff99922a0b24f9d0cc5853ae874bbc79c20eb22814ce3a912d743d4137b1f795ac3', $data[ 'data_hash' ]); |
| 183 | + $this->assertEquals( '029ef6f5c2a165215b5a92ff1a194e4a6de8c668d6193582da42713f119c1b07d8358b5cd94a3bd51c9aa50709c8533295215ce3cce8c2b61e69078d789bc3f3', $data[ 'data_hash' ]); |
183 | 184 | |
184 | 185 | $data[] = 'bar'; |
185 | 186 | $this->assertFalse( $this->fixture->bypass_minfraud( &$this->fixture, &$data )); |
Index: trunk/extensions/DonationInterface/payflowpro_gateway/extras/minfraud/minfraud.php |
— | — | @@ -1,6 +1,11 @@ |
2 | 2 | <?php |
| 3 | +/** |
| 4 | + * Validates a transaction against MaxMind's minFraud service |
| 5 | + */ |
3 | 6 | |
4 | | -class PayflowProGateway_Extras_MinFraud { |
| 7 | +$dir = dirname( __FILE__ ) . "/"; |
| 8 | +require_once( $dir . "../extras.php" ); |
| 9 | +class PayflowProGateway_Extras_MinFraud extends PayflowProGateway_Extras { |
5 | 10 | |
6 | 11 | /** |
7 | 12 | * Full response from minFraud |
— | — | @@ -15,13 +20,9 @@ |
16 | 21 | public $minfraud_license_key = NULL; |
17 | 22 | |
18 | 23 | /** |
19 | | - * File handle for log file |
20 | | - * @var public |
21 | | - */ |
22 | | - public $log_fh = NULL; |
23 | | - |
24 | | - /** |
25 | 24 | * User-definable riskScore ranges for actions to take |
| 25 | + * |
| 26 | + * Overload with $wgMinFraudActionRanges |
26 | 27 | * @var public array |
27 | 28 | */ |
28 | 29 | public $action_ranges = array( |
— | — | @@ -32,9 +33,11 @@ |
33 | 34 | ); |
34 | 35 | |
35 | 36 | function __construct( $license_key = NULL ) { |
36 | | - require_once( __FILE__ . "/../ccfd/CreditCardFraudDetection.php" ); |
| 37 | + parent::__construct(); |
| 38 | + $dir = dirname( __FILE__ ) .'/'; |
| 39 | + require_once( $dir . "ccfd/CreditCardFraudDetection.php" ); |
37 | 40 | |
38 | | - global $wgMinFraudLicenseKey, $wgMinFraudActionRanges, $wgMinFraudLog; |
| 41 | + global $wgMinFraudLicenseKey, $wgMinFraudActionRanges; |
39 | 42 | |
40 | 43 | // set the minfraud license key, go no further if we don't have it |
41 | 44 | if ( !$license_key && !$wgMinFraudLicenseKey ) { |
— | — | @@ -43,9 +46,6 @@ |
44 | 47 | $this->minfraud_license_key = ( $license_key ) ? $license_key : $wgMinFraudLicenseKey; |
45 | 48 | |
46 | 49 | if ( isset( $wgMinFraudActionRanges )) $this->action_ranges = $wgMinFraudActionRanges; |
47 | | - |
48 | | - // prepare the log file if the user has specified one |
49 | | - if ( $wgMinFraudLog ) $this->prepare_log_file( $wgMinFraudLog ); |
50 | 50 | } |
51 | 51 | |
52 | 52 | /** |
— | — | @@ -63,23 +63,19 @@ |
64 | 64 | $this->query_minfraud( $minfraud_hash ); |
65 | 65 | $pfp_gateway_object->action = $this->determine_action( $this->minfraud_response[ 'riskScore' ] ); |
66 | 66 | |
67 | | - // reset the data hash and the action |
| 67 | + // reset the data hash |
68 | 68 | if ( isset( $data[ 'data_hash' ] )) unset( $data[ 'data_hash' ] ); |
69 | | - if ( isset( $data[ 'action' ] )) unset( $data[ 'action' ] ); |
70 | | - $data[ 'data_hash' ] = $this->genereate_hash( serialize( $data )); |
71 | | - $data[ 'action' ] = $this->genereate_hash( $pfp_gateway_object->action ); |
| 69 | + $data[ 'action' ] = $this->generate_hash( $pfp_gateway_object->action ); |
| 70 | + $data[ 'data_hash' ] = $this->generate_hash( serialize( $data )); |
72 | 71 | |
73 | 72 | // log the message if the user has specified a log file |
74 | 73 | if ( $this->log_fh ) { |
75 | | - $log_message = '"'. date('c') . '"'; |
76 | | - $log_message .= "\t" . '"' . $data[ 'contribution_tracking_id' ] . '"'; |
77 | | - $log_message .= "\t" . '"' . "minFraud query" . '"'; |
78 | | - $log_message .= "\t" . '"' . $data[ 'comment' ] . '"'; |
| 74 | + $log_message = '"' . $data[ 'comment' ] . '"'; |
79 | 75 | $log_message .= "\t" . '"' . $data[ 'amount' ] . ' ' . $data[ 'currency' ] . '"'; |
80 | 76 | $log_message .= "\t" . '"' . serialize( $minfraud_hash ) . '"'; |
81 | 77 | $log_message .= "\t" . '"' . serialize( $this->minfraud_response ) . '"'; |
82 | 78 | $log_message .= "\t" . '"' . serialize( $pfp_gateway_object->actions ) . '"'; |
83 | | - $this->log( $log_message ); |
| 79 | + $this->log( $data[ 'contribution_tracking_id' ], 'minFraud query', $log_message ); |
84 | 80 | } |
85 | 81 | return TRUE; |
86 | 82 | } |
— | — | @@ -99,19 +95,21 @@ |
100 | 96 | */ |
101 | 97 | public function bypass_minfraud( &$pfp_gateway_object, &$data ) { |
102 | 98 | // if the data bits data_hash and action are not set, we need to hit minFraud |
103 | | - if ( isset( $data[ 'data_hash' ] ) && isset( $data[ 'action' ] )) { |
| 99 | + if ( strlen( $data[ 'data_hash' ] ) > 0 && strlen( $data[ 'action' ] ) > 0 ) { |
104 | 100 | $data_hash = $data[ 'data_hash' ]; // the data hash passed in by the form submission |
105 | | - $action_hash = $data[ 'action' ]; // a hash of the action to take passed in by the form submission |
106 | | - |
| 101 | + $num_attempt = $data[ 'numAttempt' ]; // the num_attempt has been increased by one, so we have to adjust slightly |
| 102 | + $data[ 'numAttempt' ] = $num_attempt - 1; |
| 103 | + |
107 | 104 | // unset these values from the data aray since they are not part of the overall data hash |
108 | 105 | unset( $data[ 'data_hash' ] ); |
109 | | - unset( $data[ 'action' ] ); |
110 | 106 | // compare the data hash to make sure it's legit |
111 | 107 | if ( $this->compare_hash( $data_hash, serialize( $data ))) { |
112 | | - $data[ 'data_hash' ] = $data_hash; |
| 108 | + $data[ 'numAttempt' ] = $num_attempt; // reset the current num attempt |
| 109 | + $data[ 'data_hash' ] = $this->generate_hash( serialize( $data )); // hash the data array |
113 | 110 | |
114 | 111 | // check to see if we have a valid action set for us to bypass minfraud |
115 | 112 | $actions = array( 'process', 'challenge', 'review', 'reject' ); |
| 113 | + $action_hash = $data[ 'action' ]; // a hash of the action to take passed in by the form submission |
116 | 114 | foreach ( $actions as $action ) { |
117 | 115 | if ( $this->compare_hash( $action_hash, $action )) { |
118 | 116 | // set the action that should be taken |
— | — | @@ -119,6 +117,9 @@ |
120 | 118 | return TRUE; |
121 | 119 | } |
122 | 120 | } |
| 121 | + } else { |
| 122 | + // log potential tamporing |
| 123 | + if ( $this->log_fh ) $this->log( $data[ 'contribution_tracking_id'], 'Data hash/action mismatch' ); |
123 | 124 | } |
124 | 125 | } |
125 | 126 | return FALSE; |
— | — | @@ -238,61 +239,4 @@ |
239 | 240 | } |
240 | 241 | } |
241 | 242 | } |
242 | | - |
243 | | - /** |
244 | | - * Prepares a log file |
245 | | - * |
246 | | - * @param string path to log file |
247 | | - * @return resource Pointer for the log file |
248 | | - */ |
249 | | - protected function prepare_log_file( $log_file ) { |
250 | | - $this->log_fh = fopen( $log_file, 'a+' ); |
251 | | - } |
252 | | - |
253 | | - /** |
254 | | - * Writes message to a log file |
255 | | - * |
256 | | - * If a log file does not exist and could not be created, |
257 | | - * do nothing. |
258 | | - * @fixme Perhaps lack of log file can be handled better, |
259 | | - * or maybe it doesn't matter? |
260 | | - * @param string The message to log |
261 | | - */ |
262 | | - public function log( $msg ) { |
263 | | - if ( !$this->log_fh ) { |
264 | | - return; |
265 | | - } |
266 | | - $msg .= "\n"; |
267 | | - fwrite( $this->log_fh, $msg ); |
268 | | - } |
269 | | - |
270 | | - /** |
271 | | - * Generate a hash of some data |
272 | | - * @param string the data to hash |
273 | | - * @return string The hash of the data |
274 | | - */ |
275 | | - public function generate_hash( $data ) { |
276 | | - global $wgMinFraudSalt; |
277 | | - return hash( "sha512", $wgMinFraudSalt . $data ); |
278 | | - } |
279 | | - |
280 | | - /** |
281 | | - * Compare a hash to the hash of some given data |
282 | | - * @param string $hash A given hash |
283 | | - * @param strin $data The data to hash and compare to $hash |
284 | | - * @return bool |
285 | | - */ |
286 | | - public function compare_hash( $hash, $data ) { |
287 | | - if ( $hash == $this->generate_hash( $data )) { |
288 | | - return TRUE; |
289 | | - } |
290 | | - return FALSE; |
291 | | - } |
292 | | - |
293 | | - /** |
294 | | - * Close the open log file handler if it's open |
295 | | - */ |
296 | | - public function __destruct() { |
297 | | - if ( $this->log_fh ) fclose( $this->log_fh ); |
298 | | - } |
299 | 243 | } |
Index: trunk/extensions/DonationInterface/payflowpro_gateway/extras/conversion_log/conversion_log.php |
— | — | @@ -0,0 +1,22 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Extra to log payflow conversion during post processing hook |
| 5 | + */ |
| 6 | +require_once( dirname( __FILE__ ) . "/../extras.php" ); |
| 7 | +class PayflowProGateway_Extras_ConversionLog extends PayflowProGateway_Extras { |
| 8 | + |
| 9 | + /** |
| 10 | + * Logs the transaction info for a conversion for payflow |
| 11 | + */ |
| 12 | + public function post_process( &$pfp_gateway_object, &$data ) { |
| 13 | + //make sure the transaction property has been set (signifying conversion) |
| 14 | + if ( !$pfp_gateway_object->payflow_transaction ) return FALSE; |
| 15 | + |
| 16 | + $this->log( |
| 17 | + $data[ 'contribution_tracking_id' ], |
| 18 | + 'Conversion', |
| 19 | + '"' . $pfp_gateway_object->payflow_transaction[ 'PNREF' ] . '"' |
| 20 | + ); |
| 21 | + return TRUE; |
| 22 | + } |
| 23 | +} |
Index: trunk/extensions/DonationInterface/payflowpro_gateway/extras/recaptcha/recaptcha.php |
— | — | @@ -0,0 +1,51 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Validates a transaction against MaxMind's minFraud service |
| 5 | + */ |
| 6 | + |
| 7 | +require_once( dirname( __FILE__ ) . "/../extras.php" ); |
| 8 | +class PayflowProGateway_Extras_reCaptcha extends PayflowProGateway_Extras { |
| 9 | + /** |
| 10 | + * Handle the challenge logic |
| 11 | + */ |
| 12 | + public function challenge( &$pfp_gateway_object, &$data ) { |
| 13 | + // if captcha posted, validate |
| 14 | + if ( isset( $_POST[ 'recaptcha_response_field' ] )) { |
| 15 | + if ( $this->validate_captcha() ){ |
| 16 | + // if validated, update the action and move on |
| 17 | + $this->log( $data[ 'contribution_tracking_id' ], 'Captcha passed' ); |
| 18 | + $pfp_gateway_object->action = "process"; |
| 19 | + return TRUE; |
| 20 | + } else { |
| 21 | + $this->log( $data[ 'contribution_tracking_id' ], 'Captcha failed' ); |
| 22 | + } |
| 23 | + } |
| 24 | + // display captcha |
| 25 | + $this->display_captcha( &$pfp_gateway_object, &$data ); |
| 26 | + return TRUE; |
| 27 | + } |
| 28 | + |
| 29 | + /** |
| 30 | + * Display the submission form with the captcha injected into it |
| 31 | + */ |
| 32 | + public function display_captcha( &$pfp_gateway_object, &$data, $error=array() ) { |
| 33 | + global $wgOut, $wgPayflowCaptcha; |
| 34 | + $form = $pfp_gateway_object->fnPayflowGenerateFormBody( $data, &$error ); |
| 35 | + $form .= Xml::openElement( 'div', array( 'id' => 'mw-donate-captcha' )); |
| 36 | + |
| 37 | + // get the captcha |
| 38 | + $form .= $wgPayflowCaptcha->getForm(); |
| 39 | + $form .= '<span class="creditcard-error-msg">' . wfMsg( 'payflowpro_gateway-error-msg-captcha-please') . '</span>'; |
| 40 | + $form .= Xml::closeElement( 'div' ); |
| 41 | + $form .= $pfp_gateway_object->fnPayflowGenerateFormSubmit( $data, &$error ); |
| 42 | + $wgOut->addHTML( $form ); |
| 43 | + } |
| 44 | + |
| 45 | + /** |
| 46 | + * Wrapper for validating the captcha submission |
| 47 | + */ |
| 48 | + public function validate_captcha() { |
| 49 | + global $wgPayflowCaptcha; |
| 50 | + return $wgPayflowCaptcha->passCaptcha(); |
| 51 | + } |
| 52 | +} |
Index: trunk/extensions/DonationInterface/payflowpro_gateway/extras/extras.php |
— | — | @@ -0,0 +1,75 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +abstract class PayflowProGateway_Extras { |
| 5 | + /** |
| 6 | + * File handle for log file |
| 7 | + * @var public |
| 8 | + */ |
| 9 | + public $log_fh = NULL; |
| 10 | + |
| 11 | + public function __construct() { |
| 12 | + global $wgPayflowGatewayLog; |
| 13 | + // prepare the log file if the user has specified one |
| 14 | + if ( $wgPayflowGatewayLog ) $this->prepare_log_file( $wgPayflowGatewayLog ); |
| 15 | + } |
| 16 | + |
| 17 | + /** |
| 18 | + * Prepared a log file |
| 19 | + * |
| 20 | + * @param string path to log file |
| 21 | + * @return resource Pointer for the log file |
| 22 | + */ |
| 23 | + protected function prepare_log_file( $log_file ){ |
| 24 | + $this->log_fh = fopen( $log_file, 'a+' ); |
| 25 | + } |
| 26 | + |
| 27 | + /** |
| 28 | + * Writes message to a log file |
| 29 | + * |
| 30 | + * If a log file does not exist and could not be created, |
| 31 | + * do nothing. |
| 32 | + * @fixme Perhaps lack of log file can be handled better? |
| 33 | + * @param string The message to log |
| 34 | + */ |
| 35 | + public function log( $id='', $status='', $data='' ) { |
| 36 | + if ( !$this->log_fh ) { |
| 37 | + return; |
| 38 | + } |
| 39 | + $msg = '"' . date( 'c' ) . '"'; |
| 40 | + $msg .= "\t" . '"' . $id . '"'; |
| 41 | + $msg .= "\t" . '"' . $status . '"'; |
| 42 | + $msg .= "\t" . $data . "\n"; |
| 43 | + fwrite( $this->log_fh, $msg ); |
| 44 | + } |
| 45 | + |
| 46 | + /** |
| 47 | + * Generate a hash of some data |
| 48 | + * @param string the data to hash |
| 49 | + * @return string The hash of the data |
| 50 | + */ |
| 51 | + public function generate_hash( $data ) { |
| 52 | + global $wgPayflowGatewaySalt; |
| 53 | + return hash( "sha512", $wgPayflowGatewaySalt . $data ); |
| 54 | + } |
| 55 | + |
| 56 | + /** |
| 57 | + * Compare a hash to the hash of some given data |
| 58 | + * @param string $hash A given hash |
| 59 | + * @param string $data The data to hash and compare to $hash |
| 60 | + * @return bool |
| 61 | + */ |
| 62 | + public function compare_hash( $hash, $data ) { |
| 63 | + if ( $hash == $this->generate_hash( $data )) { |
| 64 | + return TRUE; |
| 65 | + } |
| 66 | + |
| 67 | + return FALSE; |
| 68 | + } |
| 69 | + |
| 70 | + /** |
| 71 | + * Cloase the open log file handler if it's open |
| 72 | + */ |
| 73 | + public function __destruct() { |
| 74 | + if ( $this->log_fh ) fclose( $this->log_fh ); |
| 75 | + } |
| 76 | +} |