Index: branches/fundraising/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.body.php |
— | — | @@ -1,49 +1,13 @@ |
2 | 2 | <?php |
3 | 3 | |
4 | | -class PayflowProGateway extends UnlistedSpecialPage { |
| 4 | +class PayflowProGateway extends GatewayForm { |
5 | 5 | |
6 | 6 | /** |
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 PayflowPro 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 | | - /** |
41 | 7 | * Constructor - set up the new special page |
42 | 8 | */ |
43 | 9 | public function __construct() { |
44 | | - parent::__construct( 'PayflowProGateway' ); |
45 | | - $this->errors = $this->getPossibleErrors(); |
46 | | - |
47 | 10 | $this->adapter = new PayflowProAdapter(); |
| 11 | + parent::__construct(); //the next layer up will know who we are. |
48 | 12 | } |
49 | 13 | |
50 | 14 | /** |
— | — | @@ -52,37 +16,19 @@ |
53 | 17 | * @param $par Mixed: parameter passed to the page or null |
54 | 18 | */ |
55 | 19 | public function execute( $par ) { |
56 | | - global $wgRequest, $wgOut, $wgScriptPath, |
57 | | - $wgPayFlowProGatewayCSSVersion, |
58 | | - $wgPayflowProGatewaySalt; |
| 20 | + global $wgRequest, $wgOut, $wgExtensionAssetsPath; |
| 21 | + $CSSVersion = $this->adapter->getGlobal( 'CSSVersion' ); |
59 | 22 | |
60 | 23 | $wgOut->addExtensionStyle( |
61 | | - "{$wgScriptPath}/extensions/DonationInterface/payflowpro_gateway/payflowpro_gateway.css?284" . |
62 | | - $wgPayFlowProGatewayCSSVersion ); |
| 24 | + $wgExtensionAssetsPath . '/DonationInterface/gateway_forms/css/gateway.css?284' . |
| 25 | + $CSSVersion ); |
63 | 26 | |
64 | 27 | // Hide unneeded interface elements |
65 | 28 | $wgOut->addModules( 'donationInterface.skinOverride' ); |
66 | 29 | |
67 | | - $scriptVars = array( |
68 | | - 'payflowproGatewayErrorMsgJs' => wfMsg( 'payflowpro_gateway-error-msg-js' ), |
69 | | - 'payflowproGatewayErrorMsgEmail' => wfMsg( 'payflowpro_gateway-error-msg-email' ), |
70 | | - 'payflowproGatewayErrorMsgAmount' => wfMsg( 'payflowpro_gateway-error-msg-amount' ), |
71 | | - 'payflowproGatewayErrorMsgEmailAdd' => wfMsg( 'payflowpro_gateway-error-msg-emailAdd' ), |
72 | | - 'payflowproGatewayErrorMsgFname' => wfMsg( 'payflowpro_gateway-error-msg-fname' ), |
73 | | - 'payflowproGatewayErrorMsgLname' => wfMsg( 'payflowpro_gateway-error-msg-lname' ), |
74 | | - 'payflowproGatewayErrorMsgStreet' => wfMsg( 'payflowpro_gateway-error-msg-street' ), |
75 | | - 'payflowproGatewayErrorMsgCity' => wfMsg( 'payflowpro_gateway-error-msg-city' ), |
76 | | - 'payflowproGatewayErrorMsgState' => wfMsg( 'payflowpro_gateway-error-msg-state' ), |
77 | | - 'payflowproGatewayErrorMsgZip' => wfMsg( 'payflowpro_gateway-error-msg-zip' ), |
78 | | - 'payflowproGatewayErrorMsgCountry' => wfMsg( 'payflowpro_gateway-error-msg-country' ), |
79 | | - 'payflowproGatewayErrorMsgCardType' => wfMsg( 'payflowpro_gateway-error-msg-card_type' ), |
80 | | - 'payflowproGatewayErrorMsgCardNum' => wfMsg( 'payflowpro_gateway-error-msg-card_num' ), |
81 | | - 'payflowproGatewayErrorMsgExpiration' => wfMsg( 'payflowpro_gateway-error-msg-expiration' ), |
82 | | - 'payflowproGatewayErrorMsgCvv' => wfMsg( 'payflowpro_gateway-error-msg-cvv' ), |
83 | | - 'payflowproGatewayCVVExplain' => wfMsg( 'payflowpro_gateway-cvv-explain' ), |
84 | | - ); |
| 30 | + $gateway_id = $this->adapter->getIdentifier(); |
85 | 31 | |
86 | | - $wgOut->addScript( Skin::makeVariablesScript( $scriptVars ) ); |
| 32 | + $this->addErrorMessageScript(); |
87 | 33 | |
88 | 34 | // @fixme can this be moved into the form generators? |
89 | 35 | $js = <<<EOT |
— | — | @@ -94,69 +40,8 @@ |
95 | 41 | EOT; |
96 | 42 | $wgOut->addHeadItem( 'logolinkoverride', $js ); |
97 | 43 | |
98 | | - // find out if amount was a radio button or textbox, set amount |
99 | | - if ( isset( $_REQUEST['amount'] ) && preg_match( '/^\d+(\.(\d+)?)?$/', $wgRequest->getText( 'amount' ) ) ) { |
100 | | - $amount = $wgRequest->getText( 'amount' ); |
101 | | - } elseif ( isset( $_REQUEST['amountGiven'] ) && preg_match( '/^\d+(\.(\d+)?)?$/', $wgRequest->getText( 'amountGiven' ) ) ) { |
102 | | - $amount = number_format( $wgRequest->getText( 'amountGiven' ), 2, '.', '' ); |
103 | | - } elseif ( isset( $_REQUEST['amount'] ) ) { |
104 | | - $amount = '0.00'; |
105 | | - } elseif ( $wgRequest->getText( 'amount' ) == '-1' ) { |
106 | | - $amount = $wgRequest->getText( 'amountOther' ); |
107 | | - } else { |
108 | | - $amount = '0.00'; |
109 | | - } |
110 | | - |
111 | | - // Get array of default account values necessary for Payflow |
112 | | - require_once( 'includes/payflowUser.inc' ); |
113 | | - |
114 | | - $payflow_data = payflowUser(); |
115 | | - |
116 | | - // track the number of attempts the user has made |
117 | | - $numAttempt = $wgRequest->getVal( 'numAttempt', 0 ); |
118 | | - |
119 | | - // make a log entry if the user has submitted the cc form |
120 | | - if ( $wgRequest->wasPosted() && $wgRequest->getText( 'process', 0 ) ) { |
121 | | - self::log( $payflow_data['order_id'] . " Transaction initiated." ); |
122 | | - } else { |
123 | | - self::log( $payflow_data['order_id'] . " " . $payflow_data['i_order_id'] . " Initial credit card form request.", 'payflowpro_gateway', LOG_DEBUG ); |
124 | | - } |
125 | | - |
126 | | - // if _cache_ is requested by the user, do not set a session/token; dynamic data will be loaded via ajax |
127 | | - if ( $wgRequest->getText( '_cache_', false ) ) { |
128 | | - self::log( $payflow_data['order_id'] . " " . $payflow_data['i_order_id'] . " Cache requested", 'payflowpro_gateway', LOG_DEBUG ); |
129 | | - $cache = true; |
130 | | - $token = ''; |
131 | | - $token_match = false; |
132 | | - |
133 | | - // if we have squid caching enabled, set the maxage |
134 | | - global $wgUseSquid, $wgPayflowProSMaxAge; |
135 | | - if ( $wgUseSquid ) { |
136 | | - self::log( $payflow_data['order_id'] . " " . $payflow_data['i_order_id'] . " Setting s-max-age: " . $wgPayflowProSMaxAge, 'payflowpro_gateway', LOG_DEBUG ); |
137 | | - $wgOut->setSquidMaxage( $wgPayflowProSMaxAge ); |
138 | | - } |
139 | | - } else { |
140 | | - $cache = false; |
141 | | - |
142 | | - // establish the edit token to prevent csrf |
143 | | - $token = self::fnPayflowEditToken( $wgPayflowProGatewaySalt ); |
144 | | - |
145 | | - self::log( $payflow_data['order_id'] . " " . $payflow_data['i_order_id'] . " fnPayflowEditToken: " . $token, 'payflowpro_gateway', LOG_DEBUG ); |
146 | | - |
147 | | - // match token |
148 | | - $token_check = ( $wgRequest->getText( 'token' ) ) ? $wgRequest->getText( 'token' ) : $token; |
149 | | - $token_match = $this->fnPayflowMatchEditToken( $token_check, $wgPayflowProGatewaySalt ); |
150 | | - if ( $wgRequest->wasPosted() ) { |
151 | | - self::log( $payflow_data['order_id'] . " " . $payflow_data['i_order_id'] . " Submitted edit token: " . $wgRequest->getText( 'token', 'None' ), 'payflowpro_gateway', LOG_DEBUG ); |
152 | | - self::log( $payflow_data['order_id'] . " " . $payflow_data['i_order_id'] . " Token match: " . ($token_match ? 'true' : 'false' ), 'payflowpro_gateway', LOG_DEBUG ); |
153 | | - } |
154 | | - } |
155 | | - |
156 | 44 | $this->setHeaders(); |
157 | 45 | |
158 | | - // Populate form data |
159 | | - $data = $this->fnGetFormData( $amount, $numAttempt, $token, $payflow_data['order_id'], $payflow_data['i_order_id'] ); |
160 | | - |
161 | 46 | /** |
162 | 47 | * handle PayPal redirection |
163 | 48 | * |
— | — | @@ -164,22 +49,28 @@ |
165 | 50 | * and the PaypalRedirect form value must be true |
166 | 51 | */ |
167 | 52 | if ( $wgRequest->getText( 'PaypalRedirect', 0 ) ) { |
168 | | - $this->paypalRedirect( $data ); |
| 53 | + $this->paypalRedirect(); |
169 | 54 | return; |
170 | 55 | } |
171 | 56 | |
| 57 | + //TODO: This is short-circuiting what I really want to do here. |
| 58 | + //so stop it. |
| 59 | + $data = $this->adapter->getDisplayData(); |
| 60 | + |
172 | 61 | // dispatch forms/handling |
173 | | - if ( $token_match ) { |
174 | | - if ( $data['payment_method'] == 'processed' ) { |
| 62 | + if ( $this->adapter->checkTokens() ) { |
| 63 | + if ( $this->adapter->posted && $data['payment_method'] == 'processed' ) { |
| 64 | + // The form was submitted and the payment method has been set |
| 65 | + $this->adapter->log( "Form posted and payment method set." ); |
175 | 66 | |
176 | 67 | // increase the count of attempts |
177 | | - ++$data['numAttempt']; |
| 68 | + //++$data['numAttempt']; |
| 69 | + // Check form for errors |
| 70 | + $form_errors = $this->fnValidateForm( $data, $this->errors ); |
178 | 71 | |
179 | | - // Check form for errors and redisplay with messages |
180 | | - $form_errors = $this->fnPayflowValidateForm( $data, $this->errors ); |
181 | | - |
| 72 | + // If there were errors, redisplay form, otherwise proceed to next step |
182 | 73 | if ( $form_errors ) { |
183 | | - $this->fnPayflowDisplayForm( $data, $this->errors ); |
| 74 | + $this->displayForm( $data, $this->errors ); |
184 | 75 | } else { // The submitted form data is valid, so process it |
185 | 76 | // allow any external validators to have their way with the data |
186 | 77 | self::log( $data['order_id'] . " Preparing to query MaxMind" ); |
— | — | @@ -219,151 +110,18 @@ |
220 | 111 | } |
221 | 112 | } else { |
222 | 113 | // Display form for the first time |
223 | | - $this->fnPayflowDisplayForm( $data, $this->errors ); |
| 114 | + $this->displayForm( $data, $this->errors ); |
224 | 115 | } |
225 | 116 | } else { |
226 | | - if ( !$cache ) { |
| 117 | + if ( !$this->adapter->isCache() ) { |
227 | 118 | // if we're not caching, there's a token mismatch |
228 | | - $this->errors['general']['token-mismatch'] = wfMsg( 'payflowpro_gateway-token-mismatch' ); |
| 119 | + $this->errors['general']['token-mismatch'] = wfMsg( $gateway_id . '_gateway-token-mismatch' ); |
229 | 120 | } |
230 | | - $this->fnPayflowDisplayForm( $data, $this->errors ); |
| 121 | + $this->displayForm( $data, $this->errors ); |
231 | 122 | } |
232 | 123 | } |
233 | 124 | |
234 | 125 | /** |
235 | | - * Build and display form to user |
236 | | - * |
237 | | - * @param $data Array: array of posted user input |
238 | | - * @param $error Array: array of error messages returned by validate_form function |
239 | | - * |
240 | | - * The message at the top of the form can be edited in the payflow_gateway.i18n.php file |
241 | | - */ |
242 | | - public function fnPayflowDisplayForm( &$data, &$error ) { |
243 | | - global $wgOut, $wgRequest; |
244 | | - |
245 | | - // save contrib tracking id early to track abondonment |
246 | | - if ( $data['numAttempt'] == '0' && (!$wgRequest->getText( 'utm_source_id', false ) || $wgRequest->getText( '_nocache_' ) == 'true' ) ) { |
247 | | - $tracked = $this->fnPayflowSaveContributionTracking( $data ); |
248 | | - if ( !$tracked ) { |
249 | | - $when = time(); |
250 | | - self::log( $data['order_id'] . ' Unable to save data to the contribution_tracking table ' . $when ); |
251 | | - } |
252 | | - } |
253 | | - |
254 | | - $form_class = $this->getFormClass(); |
255 | | - $form_obj = new $form_class( $data, $error, $this->adapter ); |
256 | | - $form = $form_obj->getForm(); |
257 | | - $wgOut->addHTML( $form ); |
258 | | - } |
259 | | - |
260 | | - /** |
261 | | - * Set the form class to use to generate the CC form |
262 | | - * |
263 | | - * @param string $class_name The class name of the form to use |
264 | | - */ |
265 | | - public function setFormClass( $class_name = NULL ) { |
266 | | - if ( !$class_name ) { |
267 | | - global $wgRequest, $wgPayflowProGatewayDefaultForm; |
268 | | - $form_class = $wgRequest->getText( 'form_name', $wgPayflowProGatewayDefaultForm ); |
269 | | - |
270 | | - // make sure our form class exists before going on, if not try loading default form class |
271 | | - $class_name = "Gateway_Form_" . $form_class; |
272 | | - if ( !class_exists( $class_name ) ) { |
273 | | - $class_name_orig = $class_name; |
274 | | - $class_name = "Gateway_Form_" . $wgPayflowProGatewayDefaultForm; |
275 | | - if ( !class_exists( $class_name ) ) { |
276 | | - throw new MWException( 'Could not load form ' . $class_name_orig . ' nor default form ' . $class_name ); |
277 | | - } |
278 | | - } |
279 | | - } |
280 | | - $this->form_class = $class_name; |
281 | | - } |
282 | | - |
283 | | - /** |
284 | | - * Get the currently set form class |
285 | | - * |
286 | | - * Will set the form class if the form class not already set |
287 | | - * Using logic in setFormClass() |
288 | | - * @return string |
289 | | - */ |
290 | | - public function getFormClass() { |
291 | | - if ( !isset( $this->form_class ) ) { |
292 | | - $this->setFormClass(); |
293 | | - } |
294 | | - return $this->form_class; |
295 | | - } |
296 | | - |
297 | | - /** |
298 | | - * Checks posted form data for errors and returns array of messages |
299 | | - */ |
300 | | - private function fnPayflowValidateForm( &$data, &$error ) { |
301 | | - global $wgPayflowProGatewayPriceFloor, $wgPayflowProGatewayPriceCeiling; |
302 | | - |
303 | | - // begin with no errors |
304 | | - $error_result = '0'; |
305 | | - |
306 | | - // create the human-speak message for required fields |
307 | | - // does not include fields that are not required |
308 | | - $msg = array( |
309 | | - 'amount' => wfMsg( 'payflowpro_gateway-error-msg-amount' ), |
310 | | - 'emailAdd' => wfMsg( 'payflowpro_gateway-error-msg-emailAdd' ), |
311 | | - 'fname' => wfMsg( 'payflowpro_gateway-error-msg-fname' ), |
312 | | - 'lname' => wfMsg( 'payflowpro_gateway-error-msg-lname' ), |
313 | | - 'street' => wfMsg( 'payflowpro_gateway-error-msg-street' ), |
314 | | - 'city' => wfMsg( 'payflowpro_gateway-error-msg-city' ), |
315 | | - 'state' => wfMsg( 'payflowpro_gateway-error-msg-state' ), |
316 | | - 'zip' => wfMsg( 'payflowpro_gateway-error-msg-zip' ), |
317 | | - 'card_num' => wfMsg( 'payflowpro_gateway-error-msg-card_num' ), |
318 | | - 'expiration' => wfMsg( 'payflowpro_gateway-error-msg-expiration' ), |
319 | | - 'cvv' => wfMsg( 'payflowpro_gateway-error-msg-cvv' ), |
320 | | - ); |
321 | | - |
322 | | - // find all empty fields and create message |
323 | | - foreach ( $data as $key => $value ) { |
324 | | - if ( $value == '' || ($key == 'state' && $value == 'YY' ) ) { |
325 | | - // ignore fields that are not required |
326 | | - if ( isset( $msg[$key] ) ) { |
327 | | - $error[$key] = "**" . wfMsg( 'payflowpro_gateway-error-msg', $msg[$key] ) . "**<br />"; |
328 | | - $error_result = '1'; |
329 | | - } |
330 | | - } |
331 | | - } |
332 | | - |
333 | | - // check amount |
334 | | - if ( !preg_match( '/^\d+(\.(\d+)?)?$/', $data['amount'] ) || |
335 | | - ( ( float ) $this->convert_to_usd( $data['currency'], $data['amount'] ) < ( float ) $wgPayflowProGatewayPriceFloor || |
336 | | - ( float ) $this->convert_to_usd( $data['currency'], $data['amount'] ) > ( float ) $wgPayflowProGatewayPriceCeiling ) ) { |
337 | | - $error['invalidamount'] = wfMsg( 'payflowpro_gateway-error-msg-invalid-amount' ); |
338 | | - $error_result = '1'; |
339 | | - } |
340 | | - |
341 | | - // is email address valid? |
342 | | - $isEmail = User::isValidEmailAddr( $data['email'] ); |
343 | | - |
344 | | - // create error message (supercedes empty field message) |
345 | | - if ( !$isEmail ) { |
346 | | - $error['emailAdd'] = wfMsg( 'payflowpro_gateway-error-msg-email' ); |
347 | | - $error_result = '1'; |
348 | | - } |
349 | | - |
350 | | - // validate that credit card number entered is correct and set the card type |
351 | | - if ( preg_match( '/^3[47][0-9]{13}$/', $data['card_num'] ) ) { // american express |
352 | | - $data['card'] = 'american'; |
353 | | - } elseif ( preg_match( '/^5[1-5][0-9]{14}$/', $data['card_num'] ) ) { // mastercard |
354 | | - $data['card'] = 'mastercard'; |
355 | | - } elseif ( preg_match( '/^4[0-9]{12}(?:[0-9]{3})?$/', $data['card_num'] ) ) {// visa |
356 | | - $data['card'] = 'visa'; |
357 | | - } elseif ( preg_match( '/^6(?:011|5[0-9]{2})[0-9]{12}$/', $data['card_num'] ) ) { // discover |
358 | | - $data['card'] = 'discover'; |
359 | | - } else { // an invalid credit card number was entered |
360 | | - $error_result = '1'; |
361 | | - $error['card_num'] = wfMsg( 'payflowpro_gateway-error-msg-card-num' ); |
362 | | - } |
363 | | - |
364 | | - return $error_result; |
365 | | - } |
366 | | - |
367 | | - /** |
368 | 126 | * Sends a name-value pair string to Payflow gateway |
369 | 127 | * |
370 | 128 | * @param $data Array: array of user input |
— | — | @@ -597,43 +355,6 @@ |
598 | 356 | } |
599 | 357 | |
600 | 358 | /** |
601 | | - * Prepares the transactional message to be sent via Stomp to queueing service |
602 | | - * |
603 | | - * @param array $data |
604 | | - * @param array $resposneArray |
605 | | - * @param array $responseMsg |
606 | | - * @return array |
607 | | - */ |
608 | | - public function prepareStompTransaction( $data, $responseArray, $responseMsg ) { |
609 | | - $countries = $this->getCountries(); |
610 | | - |
611 | | - $transaction = array( ); |
612 | | - |
613 | | - // include response message |
614 | | - $transaction['response'] = $responseMsg; |
615 | | - |
616 | | - // include date |
617 | | - $transaction['date'] = time(); |
618 | | - |
619 | | - // put all data into one array |
620 | | - $optout = $this->determineOptOut( $data ); |
621 | | - $data['anonymous'] = $optout['anonymous']; |
622 | | - $data['optout'] = $optout['optout']; |
623 | | - |
624 | | - $transaction += array_merge( $data, $responseArray ); |
625 | | - |
626 | | - return $transaction; |
627 | | - } |
628 | | - |
629 | | - /** |
630 | | - * Fetch an array of country abbrevs => country names |
631 | | - */ |
632 | | - public static function getCountries() { |
633 | | - require_once( 'includes/countryCodes.inc' ); |
634 | | - return countryCodes(); |
635 | | - } |
636 | | - |
637 | | - /** |
638 | 359 | * Display response message to user with submitted user-supplied data |
639 | 360 | * |
640 | 361 | * @param $data Array: array of posted data from form |
— | — | @@ -730,617 +451,35 @@ |
731 | 452 | $this->fnPayflowUnsetEditToken(); |
732 | 453 | } |
733 | 454 | |
734 | | - /** |
735 | | - * Determine proper opt-out settings for contribution tracking |
736 | | - * |
737 | | - * because the form elements for comment anonymization and email opt-out |
738 | | - * are backwards (they are really opt-in) relative to contribution_tracking |
739 | | - * (which is opt-out), we need to reverse the values |
740 | | - */ |
741 | | - public static function determineOptOut( $data ) { |
742 | | - $optout['optout'] = ( isset( $data['email-opt'] ) && $data['email-opt'] == "1" ) ? '0' : '1'; |
743 | | - $optout['anonymous'] = ( isset( $data['comment-option'] ) && $data['comment-option'] == "1" ) ? '0' : '1'; |
744 | | - return $optout; |
745 | | - } |
| 455 | + //TODO: Remember why the heck I decided to leave this here... |
| 456 | + //arguably, it's because it's slightly more "view" related, but... still, shouldn't you get stashed |
| 457 | + //in the new GatewayForm class so we can override in chlidren if we feel like it? Odd. |
| 458 | + function addErrorMessageScript() { |
| 459 | + global $wgOut; |
| 460 | + $gateway_id = $this->adapter->getIdentifier(); |
746 | 461 | |
747 | | - function fnPayflowSaveContributionTracking( &$data ) { |
748 | | - // determine opt-out settings |
749 | | - $optout = self::determineOptOut( $data ); |
750 | | - |
751 | | - $tracked_contribution = array( |
752 | | - 'note' => $data['comment'], |
753 | | - 'referrer' => $data['referrer'], |
754 | | - 'anonymous' => $optout['anonymous'], |
755 | | - 'utm_source' => $data['utm_source'], |
756 | | - 'utm_medium' => $data['utm_medium'], |
757 | | - 'utm_campaign' => $data['utm_campaign'], |
758 | | - 'optout' => $optout['optout'], |
759 | | - 'language' => $data['language'], |
760 | | - 'ts' => '', |
| 462 | + $scriptVars = array( |
| 463 | + $gateway_id . 'GatewayErrorMsgJs' => wfMsg( $gateway_id . '_gateway-error-msg-js' ), |
| 464 | + $gateway_id . 'GatewayErrorMsgEmail' => wfMsg( $gateway_id . '_gateway-error-msg-email' ), |
| 465 | + $gateway_id . 'GatewayErrorMsgAmount' => wfMsg( $gateway_id . '_gateway-error-msg-amount' ), |
| 466 | + $gateway_id . 'GatewayErrorMsgEmailAdd' => wfMsg( $gateway_id . '_gateway-error-msg-emailAdd' ), |
| 467 | + $gateway_id . 'GatewayErrorMsgFname' => wfMsg( $gateway_id . '_gateway-error-msg-fname' ), |
| 468 | + $gateway_id . 'GatewayErrorMsgLname' => wfMsg( $gateway_id . '_gateway-error-msg-lname' ), |
| 469 | + $gateway_id . 'GatewayErrorMsgStreet' => wfMsg( $gateway_id . '_gateway-error-msg-street' ), |
| 470 | + $gateway_id . 'GatewayErrorMsgCity' => wfMsg( $gateway_id . '_gateway-error-msg-city' ), |
| 471 | + $gateway_id . 'GatewayErrorMsgState' => wfMsg( $gateway_id . '_gateway-error-msg-state' ), |
| 472 | + $gateway_id . 'GatewayErrorMsgZip' => wfMsg( $gateway_id . '_gateway-error-msg-zip' ), |
| 473 | + $gateway_id . 'GatewayErrorMsgCountry' => wfMsg( $gateway_id . '_gateway-error-msg-country' ), |
| 474 | + $gateway_id . 'GatewayErrorMsgCardType' => wfMsg( $gateway_id . '_gateway-error-msg-card_type' ), |
| 475 | + $gateway_id . 'GatewayErrorMsgCardNum' => wfMsg( $gateway_id . '_gateway-error-msg-card_num' ), |
| 476 | + $gateway_id . 'GatewayErrorMsgExpiration' => wfMsg( $gateway_id . '_gateway-error-msg-expiration' ), |
| 477 | + $gateway_id . 'GatewayErrorMsgCvv' => wfMsg( $gateway_id . '_gateway-error-msg-cvv' ), |
| 478 | + $gateway_id . 'GatewayCVVExplain' => wfMsg( $gateway_id . '_gateway-cvv-explain' ), |
761 | 479 | ); |
762 | 480 | |
763 | | - // insert tracking data and get the tracking id |
764 | | - $data['contribution_tracking_id'] = self::insertContributionTracking( $tracked_contribution ); |
765 | | - |
766 | | - if ( !$data['contribution_tracking_id'] ) { |
767 | | - return false; |
768 | | - } |
769 | | - return true; |
| 481 | + $wgOut->addScript( Skin::makeVariablesScript( $scriptVars ) ); |
770 | 482 | } |
771 | 483 | |
772 | | - /** |
773 | | - * Insert a record into the contribution_tracking table |
774 | | - * |
775 | | - * @param array $tracking_data The array of tracking data to insert to contribution_tracking |
776 | | - * NOTE: this should probably be run thru self::cleanTrackingData to ensure data integrity |
777 | | - * @return mixed Contribution tracking ID or false on failure |
778 | | - */ |
779 | | - public static function insertContributionTracking( $tracking_data ) { |
780 | | - $db = ContributionTrackingProcessor::contributionTrackingConnection(); |
781 | | - |
782 | | - if ( !$db ) { |
783 | | - return false; |
784 | | - } |
785 | | - |
786 | | - // set the time stamp if it's not already set |
787 | | - if ( !isset( $tracking_data['ts'] ) || !strlen( $tracking_data['ts'] ) ) { |
788 | | - $tracking_data['ts'] = $db->timestamp(); |
789 | | - } |
790 | | - |
791 | | - // Store the contribution data |
792 | | - if ( $db->insert( 'contribution_tracking', $tracking_data ) ) { |
793 | | - return $db->insertId(); |
794 | | - } else { |
795 | | - return false; |
796 | | - } |
797 | | - } |
798 | | - |
799 | | - /** |
800 | | - * Clean array of tracking data to contain valid fields |
801 | | - * |
802 | | - * Compares tracking data array to list of valid tracking fields and |
803 | | - * removes any extra tracking fields/data. Also sets empty values to |
804 | | - * 'null' values. |
805 | | - * @param array $tracking_data |
806 | | - * @param bool $clean_opouts If true, form opt-out values will be run through $this->determineOptOut |
807 | | - * for cleanup. |
808 | | - */ |
809 | | - public static function cleanTrackingData( $tracking_data, $clean_optouts = false ) { |
810 | | - // clean up the optout values if necessary |
811 | | - if ( $clean_optouts ) { |
812 | | - $optouts = self::determineOptOut( $tracking_data ); |
813 | | - $tracking_data['optout'] = $optouts['optout']; |
814 | | - $tracking_data['anonymous'] = $optouts['anonymous']; |
815 | | - } |
816 | | - |
817 | | - // define valid tracking fields |
818 | | - $tracking_fields = array( |
819 | | - 'note', |
820 | | - 'referrer', |
821 | | - 'anonymous', |
822 | | - 'utm_source', |
823 | | - 'utm_medium', |
824 | | - 'utm_campaign', |
825 | | - 'optout', |
826 | | - 'language', |
827 | | - 'ts' |
828 | | - ); |
829 | | - |
830 | | - // loop through tracking data and clean it up |
831 | | - foreach ( $tracking_data as $key => $value ) { |
832 | | - // Make sure we only have valid fields |
833 | | - if ( !in_array( $key, $tracking_fields ) ) { |
834 | | - unset( $tracking_data[$key] ); |
835 | | - } |
836 | | - |
837 | | - // Make all empty strings NULL |
838 | | - if ( !strlen( $value ) ) { |
839 | | - $tracking_data[$key] = null; |
840 | | - } |
841 | | - } |
842 | | - |
843 | | - return $tracking_data; |
844 | | - } |
845 | | - |
846 | | - /** |
847 | | - * Establish an 'edit' token to help prevent CSRF, etc |
848 | | - * |
849 | | - * We use this in place of $wgUser->editToken() b/c currently |
850 | | - * $wgUser->editToken() is broken (apparently by design) for |
851 | | - * anonymous users. Using $wgUser->editToken() currently exposes |
852 | | - * a security risk for non-authenticated users. Until this is |
853 | | - * resolved in $wgUser, we'll use our own methods for token |
854 | | - * handling. |
855 | | - * |
856 | | - * @var mixed $salt |
857 | | - * @return string |
858 | | - */ |
859 | | - public static function fnPayflowEditToken( $salt = '' ) { |
860 | | - |
861 | | - // make sure we have a session open for tracking a CSRF-prevention token |
862 | | - self::fnPayflowEnsureSession(); |
863 | | - |
864 | | - if ( !isset( $_SESSION['payflowEditToken'] ) ) { |
865 | | - // generate unsalted token to place in the session |
866 | | - $token = self::fnPayflowGenerateToken(); |
867 | | - $_SESSION['payflowEditToken'] = $token; |
868 | | - } else { |
869 | | - $token = $_SESSION['payflowEditToken']; |
870 | | - } |
871 | | - |
872 | | - if ( is_array( $salt ) ) { |
873 | | - $salt = implode( "|", $salt ); |
874 | | - } |
875 | | - return md5( $token . $salt ) . EDIT_TOKEN_SUFFIX; |
876 | | - } |
877 | | - |
878 | | - /** |
879 | | - * Generate a token string |
880 | | - * |
881 | | - * @var mixed $salt |
882 | | - * @return string |
883 | | - */ |
884 | | - public static function fnPayflowGenerateToken( $salt = '' ) { |
885 | | - $token = dechex( mt_rand() ) . dechex( mt_rand() ); |
886 | | - return md5( $token . $salt ); |
887 | | - } |
888 | | - |
889 | | - /** |
890 | | - * Determine the validity of a token |
891 | | - * |
892 | | - * @var string $val |
893 | | - * @var mixed $salt |
894 | | - * @return bool |
895 | | - */ |
896 | | - function fnPayflowMatchEditToken( $val, $salt = '' ) { |
897 | | - // fetch a salted version of the session token |
898 | | - $sessionToken = self::fnPayflowEditToken( $salt ); |
899 | | - if ( $val != $sessionToken ) { |
900 | | - wfDebug( "PayflowproGateway::fnPayflowMatchEditToken: broken session data\n" ); |
901 | | - } |
902 | | - return $val == $sessionToken; |
903 | | - } |
904 | | - |
905 | | - /** |
906 | | - * Unset the payflow edit token from a user's session |
907 | | - */ |
908 | | - function fnPayflowUnsetEditToken() { |
909 | | - unset( $_SESSION['payflowEditToken'] ); |
910 | | - } |
911 | | - |
912 | | - /** |
913 | | - * Ensure that we have a session set for the current user |
914 | | - * |
915 | | - * If we do not have a session set for the current user, |
916 | | - * start the session. |
917 | | - */ |
918 | | - public static function fnPayflowEnsureSession() { |
919 | | - // if the session is already started, do nothing |
920 | | - if ( session_id() ) |
921 | | - return; |
922 | | - |
923 | | - // otherwise, fire it up using global mw function wfSetupSession |
924 | | - wfSetupSession(); |
925 | | - } |
926 | | - |
927 | | - /** |
928 | | - * Populate the $data array for the credit card form |
929 | | - * |
930 | | - * Provides a way to prepopulate the form with test data using $wgDonationInterfaceTest |
931 | | - * @return array |
932 | | - */ |
933 | | - public function fnGetFormData( $amount, $numAttempt, $token, $order_id, $i_order_id=0 ) { |
934 | | - global $wgDonationInterfaceTest, $wgRequest; |
935 | | - |
936 | | - // fetch ID for the url reference for OWA tracking |
937 | | - $owa_ref = $wgRequest->getText( 'owa_ref', null ); |
938 | | - if ( $owa_ref != null && !is_numeric( $owa_ref ) ) { |
939 | | - $owa_ref = $this->get_owa_ref_id( $owa_ref ); |
940 | | - } |
941 | | - |
942 | | - // if we're in testing mode and an action hasn't yet be specified, prepopulate the form |
943 | | - if ( !$wgRequest->getText( 'action', false ) && !$wgRequest->getText( 'process', 0 ) && $wgDonationInterfaceTest ) { |
944 | | - // define arrays of cc's and cc #s for random selection |
945 | | - $cards = array( 'american' ); |
946 | | - $card_nums = array( |
947 | | - 'american' => array( |
948 | | - 378282246310005 |
949 | | - ), |
950 | | - ); |
951 | | - |
952 | | - // randomly select a credit card |
953 | | - $card_index = array_rand( $cards ); |
954 | | - |
955 | | - // randomly select a credit card # |
956 | | - $card_num_index = array_rand( $card_nums[$cards[$card_index]] ); |
957 | | - |
958 | | - $data = array( |
959 | | - 'amount' => ( $amount != "0.00" ) ? $amount : "35", |
960 | | - 'amountOther' => '', |
961 | | - 'email' => 'test@example.com', |
962 | | - 'fname' => 'Tester', |
963 | | - 'mname' => 'T.', |
964 | | - 'lname' => 'Testington', |
965 | | - 'street' => '548 Market St.', |
966 | | - 'city' => 'San Francisco', |
967 | | - 'state' => 'CA', |
968 | | - 'zip' => '94104', |
969 | | - 'country' => 'US', |
970 | | - 'fname2' => 'Testy', |
971 | | - 'lname2' => 'Testerson', |
972 | | - 'street2' => '123 Telegraph Ave.', |
973 | | - 'city2' => 'Berkeley', |
974 | | - 'state2' => 'CA', |
975 | | - 'zip2' => '94703', |
976 | | - 'country2' => 'US', |
977 | | - 'size' => 'small', |
978 | | - 'premium_language' => 'es', |
979 | | - 'card_num' => $card_nums[$cards[$card_index]][$card_num_index], |
980 | | - 'card_type' => $cards[$card_index], |
981 | | - 'expiration' => date( 'my', strtotime( '+1 year 1 month' ) ), |
982 | | - 'cvv' => '001', |
983 | | - 'currency' => 'USD', |
984 | | - 'payment_method' => $wgRequest->getText( 'payment_method' ), |
985 | | - 'order_id' => $order_id, |
986 | | - 'i_order_id' => $i_order_id, |
987 | | - 'numAttempt' => $numAttempt, |
988 | | - 'referrer' => 'http://www.baz.test.com/index.php?action=foo&action=bar', |
989 | | - 'utm_source' => self::getUtmSource(), |
990 | | - 'utm_medium' => $wgRequest->getText( 'utm_medium' ), |
991 | | - 'utm_campaign' => $wgRequest->getText( 'utm_campaign' ), |
992 | | - 'language' => 'en', |
993 | | - 'comment-option' => $wgRequest->getText( 'comment-option' ), |
994 | | - 'comment' => $wgRequest->getText( 'comment' ), |
995 | | - 'email-opt' => $wgRequest->getText( 'email-opt' ), |
996 | | - 'test_string' => $wgRequest->getText( 'process' ), |
997 | | - 'token' => $token, |
998 | | - 'contribution_tracking_id' => $wgRequest->getText( 'contribution_tracking_id' ), |
999 | | - 'data_hash' => $wgRequest->getText( 'data_hash' ), |
1000 | | - 'action' => $wgRequest->getText( 'action' ), |
1001 | | - 'gateway' => 'payflowpro', |
1002 | | - 'owa_session' => $wgRequest->getText( 'owa_session', null ), |
1003 | | - 'owa_ref' => $owa_ref, |
1004 | | - ); |
1005 | | - } else { |
1006 | | - $data = array( |
1007 | | - 'amount' => $amount, |
1008 | | - 'amountOther' => $wgRequest->getText( 'amountOther' ), |
1009 | | - 'email' => $wgRequest->getText( 'emailAdd' ), |
1010 | | - 'fname' => $wgRequest->getText( 'fname' ), |
1011 | | - 'mname' => $wgRequest->getText( 'mname' ), |
1012 | | - 'lname' => $wgRequest->getText( 'lname' ), |
1013 | | - 'street' => $wgRequest->getText( 'street' ), |
1014 | | - 'city' => $wgRequest->getText( 'city' ), |
1015 | | - 'state' => $wgRequest->getText( 'state' ), |
1016 | | - 'zip' => $wgRequest->getText( 'zip' ), |
1017 | | - 'country' => $wgRequest->getText( 'country' ), |
1018 | | - 'fname2' => $wgRequest->getText( 'fname' ), |
1019 | | - 'lname2' => $wgRequest->getText( 'lname' ), |
1020 | | - 'street2' => $wgRequest->getText( 'street' ), |
1021 | | - 'city2' => $wgRequest->getText( 'city' ), |
1022 | | - 'state2' => $wgRequest->getText( 'state' ), |
1023 | | - 'zip2' => $wgRequest->getText( 'zip' ), |
1024 | | - /** |
1025 | | - * For legacy reasons, we might get a 0-length string passed into the form for country2. If this happens, we need to set country2 |
1026 | | - * to be 'country' for downstream processing (until we fully support passing in two separate addresses). I thought about completely |
1027 | | - * disabling country2 support in the forms, etc but realized there's a chance it'll be resurrected shortly. Hence this silly hack. |
1028 | | - */ |
1029 | | - 'country2' => ( strlen( $wgRequest->getText( 'country2' ) )) ? $wgRequest->getText( 'country2' ) : $wgRequest->getText( 'country' ), |
1030 | | - 'size' => $wgRequest->getText( 'size' ), |
1031 | | - 'premium_language' => $wgRequest->getText( 'premium_language', "en" ), |
1032 | | - 'card_num' => str_replace( ' ', '', $wgRequest->getText( 'card_num' ) ), |
1033 | | - 'card_type' => $wgRequest->getText( 'card_type' ), |
1034 | | - 'expiration' => $wgRequest->getText( 'mos' ) . substr( $wgRequest->getText( 'year' ), 2, 2 ), |
1035 | | - 'cvv' => $wgRequest->getText( 'cvv' ), |
1036 | | - 'currency' => $wgRequest->getText( 'currency_code' ), |
1037 | | - 'payment_method' => $wgRequest->getText( 'payment_method' ), |
1038 | | - 'order_id' => $order_id, |
1039 | | - 'i_order_id' => $i_order_id, |
1040 | | - 'numAttempt' => $numAttempt, |
1041 | | - 'referrer' => ( $wgRequest->getVal( 'referrer' ) ) ? $wgRequest->getVal( 'referrer' ) : $wgRequest->getHeader( 'referer' ), |
1042 | | - 'utm_source' => self::getUtmSource(), |
1043 | | - 'utm_medium' => $wgRequest->getText( 'utm_medium' ), |
1044 | | - 'utm_campaign' => $wgRequest->getText( 'utm_campaign' ), |
1045 | | - // try to honor the user-set language (uselang), otherwise the language set in the URL (language) |
1046 | | - 'language' => $wgRequest->getText( 'uselang', $wgRequest->getText( 'language' ) ), |
1047 | | - 'comment-option' => $wgRequest->getText( 'comment-option' ), |
1048 | | - 'comment' => $wgRequest->getText( 'comment' ), |
1049 | | - 'email-opt' => $wgRequest->getText( 'email-opt' ), |
1050 | | - 'test_string' => $wgRequest->getText( 'process' ), // for showing payflow string during testing |
1051 | | - 'token' => $token, |
1052 | | - 'contribution_tracking_id' => $wgRequest->getText( 'contribution_tracking_id' ), |
1053 | | - 'data_hash' => $wgRequest->getText( 'data_hash' ), |
1054 | | - 'action' => $wgRequest->getText( 'action' ), |
1055 | | - 'gateway' => 'payflowpro', // this may need to become dynamic in the future |
1056 | | - 'owa_session' => $wgRequest->getText( 'owa_session', null ), |
1057 | | - 'owa_ref' => $owa_ref, |
1058 | | - ); |
1059 | | - } |
1060 | | - |
1061 | | - // sanitize user input |
1062 | | - array_walk( $data, array( $this, 'sanitizeInput' ) ); |
1063 | | - |
1064 | | - return $data; |
1065 | | - } |
1066 | | - |
1067 | | - /** |
1068 | | - * Sanitize user input |
1069 | | - * |
1070 | | - * Intended to be used with something like array_walk |
1071 | | - * |
1072 | | - * @param $value The value of the array |
1073 | | - * @param $key The key of the array |
1074 | | - * @param $flags The flag constant for htmlspecialchars |
1075 | | - * @param $double_encode Whether or not to double-encode strings |
1076 | | - */ |
1077 | | - public function sanitizeInput( &$value, $key, $flags=ENT_COMPAT, $double_encode=false ) { |
1078 | | - $value = htmlspecialchars( $value, $flags, 'UTF-8', $double_encode ); |
1079 | | - } |
1080 | | - |
1081 | | - public function getPossibleErrors() { |
1082 | | - return array( |
1083 | | - 'general' => '', |
1084 | | - 'retryMsg' => '', |
1085 | | - 'invalidamount' => '', |
1086 | | - 'card_num' => '', |
1087 | | - 'card_type' => '', |
1088 | | - 'cvv' => '', |
1089 | | - 'fname' => '', |
1090 | | - 'lname' => '', |
1091 | | - 'city' => '', |
1092 | | - 'country' => '', |
1093 | | - 'street' => '', |
1094 | | - 'state' => '', |
1095 | | - 'zip' => '', |
1096 | | - 'emailAdd' => '', |
1097 | | - ); |
1098 | | - } |
1099 | | - |
1100 | | - /** |
1101 | | - * Get the utm_source string |
1102 | | - * |
1103 | | - * Checks to see if the utm_source is set properly for the credit card |
1104 | | - * form including any cc form variants (identified by utm_source_id). If |
1105 | | - * anything cc form related is out of place for the utm_source, this |
1106 | | - * will fix it. |
1107 | | - * |
1108 | | - * the utm_source is structured as: banner.landing_page.payment_instrument |
1109 | | - * |
1110 | | - * @param string $utm_source The utm_source for tracking - if not passed directly, |
1111 | | - * we try to figure it out from the request object |
1112 | | - * @param int $utm_source_id The utm_source_id for tracking - if not passed directly, |
1113 | | - * we try to figure it out from the request object |
1114 | | - * @return string The full utm_source |
1115 | | - */ |
1116 | | - public static function getUtmSource( $utm_source = null, $utm_source_id = null ) { |
1117 | | - global $wgRequest; |
1118 | | - |
1119 | | - /** |
1120 | | - * fetch whatever was passed in as the utm_source |
1121 | | - * |
1122 | | - * if utm_source was not passed in as a param, we try to divine it from |
1123 | | - * the request. if it's not set there, no big deal, we'll just be |
1124 | | - * missing some tracking data. |
1125 | | - */ |
1126 | | - if ( is_null( $utm_source ) ) { |
1127 | | - $utm_source = $wgRequest->getText( 'utm_source' ); |
1128 | | - } |
1129 | | - |
1130 | | - /** |
1131 | | - * if we have a utm_source_id, then the user is on a single-step credit card form. |
1132 | | - * if that's the case, we treat the single-step credit card form as a landing page, |
1133 | | - * which we label as cc#, where # = the utm_source_id |
1134 | | - */ |
1135 | | - if ( is_null( $utm_source_id ) ) { |
1136 | | - $utm_source_id = $wgRequest->getVal( 'utm_source_id', 0 ); |
1137 | | - } |
1138 | | - |
1139 | | - // this is how the CC portion of the utm_source should be defined |
1140 | | - $correct_cc_source = ( $utm_source_id ) ? 'cc' . $utm_source_id . '.cc' : 'cc'; |
1141 | | - |
1142 | | - // check to see if the utm_source is already correct - if so, return |
1143 | | - if ( preg_match( '/' . str_replace( ".", "\.", $correct_cc_source ) . '$/', $utm_source ) ) { |
1144 | | - return $utm_source; |
1145 | | - } |
1146 | | - |
1147 | | - // split the utm_source into its parts for easier manipulation |
1148 | | - $source_parts = explode( ".", $utm_source ); |
1149 | | - |
1150 | | - // if there are no sourceparts element, then the banner portion of the string needs to be set. |
1151 | | - // since we don't know what it is, set it to an empty string |
1152 | | - if ( !count( $source_parts ) ) |
1153 | | - $source_parts[0] = ''; |
1154 | | - |
1155 | | - // if the utm_source_id is set, set the landing page portion of the string to cc# |
1156 | | - $source_parts[1] = ( $utm_source_id ) ? 'cc' . $utm_source_id : ( isset( $source_parts[1] ) ? $source_parts[1] : '' ); |
1157 | | - |
1158 | | - // the payment instrument portion should always be 'cc' if this method is being accessed |
1159 | | - $source_parts[2] = 'cc'; |
1160 | | - |
1161 | | - // return a reconstructed string |
1162 | | - return implode( ".", $source_parts ); |
1163 | | - } |
1164 | | - |
1165 | | - /** |
1166 | | - * Update contribution_tracking table |
1167 | | - * |
1168 | | - * @param array $data Form data |
1169 | | - * @param bool $force If set to true, will ensure that contribution tracking is updated |
1170 | | - */ |
1171 | | - public function updateContributionTracking( &$data, $force = false ) { |
1172 | | - // ony update contrib tracking if we're coming from a single-step landing page |
1173 | | - // which we know with cc# in utm_source or if force=true or if contribution_tracking_id is not set |
1174 | | - if ( !$force && |
1175 | | - !preg_match( "/cc[0-9]/", $data['utm_source'] ) && |
1176 | | - is_numeric( $data['contribution_tracking_id'] ) ) { |
1177 | | - return; |
1178 | | - } |
1179 | | - |
1180 | | - |
1181 | | - // determine opt-out settings |
1182 | | - $optout = self::determineOptOut( $data ); |
1183 | | - |
1184 | | - $db = payflowGatewayConnection(); |
1185 | | - |
1186 | | - if ( !$db ) { |
1187 | | - return true; |
1188 | | - } |
1189 | | - |
1190 | | - $tracked_contribution = array( |
1191 | | - 'note' => $data['comment'], |
1192 | | - 'referrer' => $data['referrer'], |
1193 | | - 'anonymous' => $optout['anonymous'], |
1194 | | - 'utm_source' => $data['utm_source'], |
1195 | | - 'utm_medium' => $data['utm_medium'], |
1196 | | - 'utm_campaign' => $data['utm_campaign'], |
1197 | | - 'owa_session' => $data['owa_session'], |
1198 | | - 'owa_ref' => $data['owa_ref'], |
1199 | | - 'optout' => $optout['optout'], |
1200 | | - 'language' => $data['language'], |
1201 | | - ); |
1202 | | - |
1203 | | - // Make all empty strings NULL |
1204 | | - foreach ( $tracked_contribution as $key => $value ) { |
1205 | | - if ( $value === '' ) { |
1206 | | - $tracked_contribution[$key] = null; |
1207 | | - } |
1208 | | - } |
1209 | | - |
1210 | | - // if contrib tracking id is not already set, we need to insert the data, otherwise update |
1211 | | - if ( !$data['contribution_tracking_id'] ) { |
1212 | | - $data['contribution_tracking_id'] = $this->insertContributionTracking( $tracked_contribution ); |
1213 | | - } else { |
1214 | | - $db->update( 'contribution_tracking', $tracked_contribution, array( 'id' => $data['contribution_tracking_id'] ) ); |
1215 | | - } |
1216 | | - } |
1217 | | - |
1218 | | - /** |
1219 | | - * Handle redirection of form content to PayPal |
1220 | | - * |
1221 | | - * @fixme If we can update contrib tracking table in ContributionTracking |
1222 | | - * extension, we can probably get rid of this method and just submit the form |
1223 | | - * directly to the paypal URL, and have all processing handled by ContributionTracking |
1224 | | - * This would make this a lot less hack-ish |
1225 | | - */ |
1226 | | - public function paypalRedirect( &$data ) { |
1227 | | - global $wgPayflowProGatewayPaypalURL, $wgOut; |
1228 | | - |
1229 | | - // if we don't have a URL enabled throw a graceful error to the user |
1230 | | - if ( !strlen( $wgPayflowProGatewayPaypalURL ) ) { |
1231 | | - $this->errors['general']['nopaypal'] = wfMsg( 'payflow_gateway-error-msg-nopaypal' ); |
1232 | | - return; |
1233 | | - } |
1234 | | - |
1235 | | - // update the utm source to set the payment instrument to pp rather than cc |
1236 | | - $utm_source_parts = explode( ".", $data['utm_source'] ); |
1237 | | - $utm_source_parts[2] = 'pp'; |
1238 | | - $data['utm_source'] = implode( ".", $utm_source_parts ); |
1239 | | - $data['gateway'] = 'paypal'; |
1240 | | - $data['currency_code'] = $data['currency']; |
1241 | | - /** |
1242 | | - * update contribution tracking |
1243 | | - */ |
1244 | | - $this->updateContributionTracking( $data, true ); |
1245 | | - |
1246 | | - $wgPayflowProGatewayPaypalURL .= "/" . $data['language'] . "?gateway=paypal"; |
1247 | | - |
1248 | | - // submit the data to the paypal redirect URL |
1249 | | - $wgOut->redirect( $wgPayflowProGatewayPaypalURL . '&' . http_build_query( $data ) ); |
1250 | | - } |
1251 | | - |
1252 | | - public static function log( $msg, $identifier='payflowpro_gateway', $log_level=LOG_INFO ) { |
1253 | | - global $wgPayflowGatewayUseSyslog; |
1254 | | - |
1255 | | - // if we're not using the syslog facility, use wfDebugLog |
1256 | | - if ( !$wgPayflowGatewayUseSyslog ) { |
1257 | | - wfDebugLog( $identifier, $msg ); |
1258 | | - return; |
1259 | | - } |
1260 | | - |
1261 | | - // otherwise, use syslogging |
1262 | | - openlog( $identifier, LOG_ODELAY, LOG_SYSLOG ); |
1263 | | - syslog( $log_level, $msg ); |
1264 | | - closelog(); |
1265 | | - } |
1266 | | - |
1267 | | - /** |
1268 | | - * Convert an amount for a particular currency to an amount in USD |
1269 | | - * |
1270 | | - * This is grosley rudimentary and likely wildly inaccurate. |
1271 | | - * This mimicks the hard-coded values used by the WMF to convert currencies |
1272 | | - * for validatoin on the front-end on the first step landing pages of their |
1273 | | - * donation process - the idea being that we can get a close approximation |
1274 | | - * of converted currencies to ensure that contributors are not going above |
1275 | | - * or below the price ceiling/floor, even if they are using a non-US currency. |
1276 | | - * |
1277 | | - * In reality, this probably ought to use some sort of webservice to get real-time |
1278 | | - * conversion rates. |
1279 | | - * |
1280 | | - * @param $currency_code |
1281 | | - * @param $amount |
1282 | | - * @return unknown_type |
1283 | | - */ |
1284 | | - public function convert_to_usd( $currency_code, $amount ) { |
1285 | | - switch ( strtoupper( $currency_code ) ) { |
1286 | | - case 'USD': |
1287 | | - $usd_amount = $amount / 1; |
1288 | | - break; |
1289 | | - case 'GBP': |
1290 | | - $usd_amount = $amount / 1; |
1291 | | - break; |
1292 | | - case 'EUR': |
1293 | | - $usd_amount = $amount / 1; |
1294 | | - break; |
1295 | | - case 'AUD': |
1296 | | - $usd_amount = $amount / 2; |
1297 | | - break; |
1298 | | - case 'CAD': |
1299 | | - $usd_amount = $amount / 1; |
1300 | | - break; |
1301 | | - case 'CHF': |
1302 | | - $usd_amount = $amount / 1; |
1303 | | - break; |
1304 | | - case 'CZK': |
1305 | | - $usd_amount = $amount / 20; |
1306 | | - break; |
1307 | | - case 'DKK': |
1308 | | - $usd_amount = $amount / 5; |
1309 | | - break; |
1310 | | - case 'HKD': |
1311 | | - $usd_amount = $amount / 10; |
1312 | | - break; |
1313 | | - case 'HUF': |
1314 | | - $usd_amount = $amount / 200; |
1315 | | - break; |
1316 | | - case 'JPY': |
1317 | | - $usd_amount = $amount / 100; |
1318 | | - break; |
1319 | | - case 'NZD': |
1320 | | - $usd_amount = $amount / 2; |
1321 | | - break; |
1322 | | - case 'NOK': |
1323 | | - $usd_amount = $amount / 10; |
1324 | | - break; |
1325 | | - case 'PLN': |
1326 | | - $usd_amount = $amount / 5; |
1327 | | - break; |
1328 | | - case 'SGD': |
1329 | | - $usd_amount = $amount / 2; |
1330 | | - break; |
1331 | | - case 'SEK': |
1332 | | - $usd_amount = $amount / 10; |
1333 | | - break; |
1334 | | - case 'ILS': |
1335 | | - $usd_amount = $amount / 5; |
1336 | | - break; |
1337 | | - default: |
1338 | | - $usd_amount = $amount; |
1339 | | - break; |
1340 | | - } |
1341 | | - |
1342 | | - return $usd_amount; |
1343 | | - } |
1344 | | - |
1345 | 484 | } |
1346 | 485 | |
1347 | 486 | // end class |
Index: branches/fundraising/extensions/DonationInterface/payflowpro_gateway/payflowpro.adapter.php |
— | — | @@ -1,154 +1,123 @@ |
2 | 2 | <?php |
3 | 3 | |
4 | 4 | class PayflowProAdapter extends GatewayAdapter { |
5 | | - //Contains the map of THEIR var names, to OURS. |
6 | | - //I'd have gone the other way, but we'd run into 1:many pretty quick. |
7 | | - |
8 | 5 | const GATEWAY_NAME = 'Payflow Pro'; |
9 | 6 | const IDENTIFIER = 'payflowpro_gateway'; |
10 | 7 | const COMMUNICATION_TYPE = 'namevalue'; |
11 | 8 | const GLOBAL_PREFIX = 'wgPayflowProGateway'; |
12 | 9 | |
13 | | - /** |
14 | | - * stageData should alter the postdata array in all ways necessary in preparation for |
15 | | - * communication with the gateway. |
16 | | - */ |
17 | | - function stageData() { |
18 | | - |
19 | | - } |
20 | | - |
21 | 10 | function defineAccountInfo() { |
22 | 11 | $this->accountInfo = array( |
23 | | - 'MERCHANTID' => self::getGlobal( 'MerchantID' ), |
24 | | - //'IPADDRESS' => '', //TODO: Not sure if this should be OUR ip, or the user's ip. Hurm. |
25 | | - 'VERSION' => "1.0", |
| 12 | + 'PARTNER' => self::getGlobal( 'PartnerID' ), // PayPal or original authorized reseller |
| 13 | + 'VENDOR' => self::getGlobal( 'VendorID' ), // paypal merchant login ID |
| 14 | + 'USER' => self::getGlobal( 'UserID' ), // if one or more users are set up, authorized user ID, else same as VENDOR |
| 15 | + 'PWD' => self::getGlobal( 'Password' ), // merchant login password |
26 | 16 | ); |
27 | 17 | } |
28 | 18 | |
29 | 19 | function defineVarMap() { |
30 | 20 | $this->var_map = array( |
31 | | - 'ORDERID' => 'order_id', |
32 | | - 'AMOUNT' => 'amount', |
33 | | - 'CURRENCYCODE' => 'currency', |
34 | | - 'LANGUAGECODE' => 'language', |
35 | | - 'COUNTRYCODE' => 'country', |
36 | | - 'MERCHANTREFERENCE' => 'order_id', |
37 | | - 'RETURNURL' => 'returnto', //I think. It might not even BE here yet. Boo-urns. |
38 | | - 'IPADDRESS' => 'user_ip', //TODO: Not sure if this should be OUR ip, or the user's ip. Hurm. |
| 21 | + 'ACCT' => 'card_num', |
| 22 | + 'EXPDATE' => 'expiration', |
| 23 | + 'AMT' => 'amount', |
| 24 | + 'FIRSTNAME' => 'fname', |
| 25 | + 'LASTNAME' => 'lname', |
| 26 | + 'STREET' => 'street', |
| 27 | + 'CITY' => 'city', |
| 28 | + 'STATE' => 'state', |
| 29 | + 'COUNTRY' => 'country', |
| 30 | + 'ZIP' => 'zip', |
| 31 | + 'INVNUM' => 'order_id', |
| 32 | + 'CVV2' => 'cvv', |
| 33 | + 'CURRENCY' => 'currency', |
| 34 | + 'CUSTIP' => 'user_ip', |
| 35 | +// 'ORDERID' => 'order_id', |
| 36 | +// 'AMOUNT' => 'amount', |
| 37 | +// 'CURRENCYCODE' => 'currency', |
| 38 | +// 'LANGUAGECODE' => 'language', |
| 39 | +// 'COUNTRYCODE' => 'country', |
| 40 | +// 'MERCHANTREFERENCE' => 'order_id', |
| 41 | +// 'RETURNURL' => 'returnto', //I think. It might not even BE here yet. Boo-urns. |
| 42 | +// 'IPADDRESS' => 'user_ip', //TODO: Not sure if this should be OUR ip, or the user's ip. Hurm. |
39 | 43 | ); |
40 | 44 | } |
41 | 45 | |
42 | 46 | function defineReturnValueMap() { |
43 | | - $this->return_value_map = array( |
44 | | - 'OK' => true, |
45 | | - 'NOK' => false, |
46 | | - ); |
| 47 | + $this->return_value_map = array( ); //we don't really need this... maybe. |
47 | 48 | } |
48 | 49 | |
49 | 50 | function defineTransactions() { |
50 | 51 | $this->transactions = array( ); |
51 | 52 | |
52 | | - $this->transactions['INSERT_ORDERWITHPAYMENT'] = array( |
| 53 | + $this->transactions['Card'] = array( |
53 | 54 | 'request' => array( |
54 | | - 'REQUEST' => array( |
55 | | - 'ACTION', |
56 | | - 'META' => array( |
57 | | - 'MERCHANTID', |
58 | | - // 'IPADDRESS', |
59 | | - 'VERSION' |
60 | | - ), |
61 | | - 'PARAMS' => array( |
62 | | - 'ORDER' => array( |
63 | | - 'ORDERID', |
64 | | - 'AMOUNT', |
65 | | - 'CURRENCYCODE', |
66 | | - 'LANGUAGECODE', |
67 | | - 'COUNTRYCODE', |
68 | | - 'MERCHANTREFERENCE' |
69 | | - ), |
70 | | - 'PAYMENT' => array( |
71 | | - 'PAYMENTPRODUCTID', |
72 | | - 'AMOUNT', |
73 | | - 'CURRENCYCODE', |
74 | | - 'LANGUAGECODE', |
75 | | - 'COUNTRYCODE', |
76 | | - 'HOSTEDINDICATOR', |
77 | | - 'RETURNURL', |
78 | | - ) |
79 | | - ) |
80 | | - ) |
| 55 | + 'TRXTYPE', |
| 56 | + 'TENDER', |
| 57 | + 'USER', |
| 58 | + 'VENDOR', |
| 59 | + 'PARTNER', |
| 60 | + 'PWD', |
| 61 | + 'ACCT', |
| 62 | + 'EXPDATE', |
| 63 | + 'AMT', |
| 64 | + 'FIRSTNAME', |
| 65 | + 'LASTNAME', |
| 66 | + 'STREET', |
| 67 | + 'CITY', |
| 68 | + 'STATE', |
| 69 | + 'COUNTRY', |
| 70 | + 'ZIP', |
| 71 | + 'INVNUM', |
| 72 | + 'CVV2', |
| 73 | + 'CURRENCY', |
| 74 | + 'VERBOSITY', |
| 75 | + 'CUSTIP', |
81 | 76 | ), |
82 | 77 | 'values' => array( |
83 | | - 'ACTION' => 'INSERT_ORDERWITHPAYMENT', |
84 | | - 'HOSTEDINDICATOR' => '1', |
85 | | - 'PAYMENTPRODUCTID' => '3', |
| 78 | + 'TRXTYPE' => 'S', |
| 79 | + 'TENDER' => 'C', |
| 80 | + 'VERBOSITY' => 'MEDIUM', |
86 | 81 | ), |
87 | 82 | ); |
88 | | - |
89 | | - $this->transactions['TEST_CONNECTION'] = array( |
90 | | - 'request' => array( |
91 | | - 'REQUEST' => array( |
92 | | - 'ACTION', |
93 | | - 'META' => array( |
94 | | - 'MERCHANTID', |
95 | | -// 'IPADDRESS', |
96 | | - 'VERSION' |
97 | | - ), |
98 | | - 'PARAMS' => array( ) |
99 | | - ) |
100 | | - ), |
101 | | - 'values' => array( |
102 | | - 'ACTION' => 'TEST_CONNECTION' |
103 | | - ) |
104 | | - ); |
105 | 83 | } |
106 | 84 | |
107 | | - function do_transaction( $transaction ) { |
108 | | - $this->currentTransaction( $transaction ); |
109 | | - if ( $this->getCommunicationType() === 'xml' ) { |
110 | | - $xml = $this->buildRequestXML(); |
111 | | - $response = $this->curl_transaction( $xml ); |
112 | | - //put the response in a universal form, and return it. |
113 | | - } |
114 | | - |
115 | | - //TODO: Actually pull these status messages from somewhere legit. |
116 | | - if ( $response['result'] !== false ) { |
117 | | - //now, parse the thing. |
118 | | - |
119 | | - |
120 | | - if ( $response['status'] === true ) { |
121 | | - $response['message'] = "$transaction Transaction Successful!"; |
122 | | - } elseif ( $response['status'] === false ) { |
123 | | - $response['message'] = "$transaction Transaction FAILED!"; |
124 | | - } else { |
125 | | - $response['message'] = "$transaction Transaction... weird. I have no idea what happened there."; |
126 | | - } |
127 | | - } |
128 | | - |
129 | | - return $response; |
130 | | - |
131 | | - //speaking of universal form: |
132 | | - //$result['status'] = something I wish could be boiled down to a bool, but that's way too optimistic, I think. |
133 | | - //$result['message'] = whatever we want to display back? |
134 | | - //$result['errors'][]['code'] = their error code |
135 | | - //$result['errors'][]['value'] = Error message |
136 | | - //$result['return'][$whatever] = values they pass back to us for whatever reason. We might... log it, or pieces of it, or something? |
137 | | - } |
138 | | - |
139 | 85 | /** |
140 | 86 | * Take the entire response string, and strip everything we don't care about. |
141 | 87 | * For instance: If it's XML, we only want correctly-formatted XML. Headers must be killed off. |
142 | 88 | * return a string. |
143 | 89 | */ |
144 | | - function getTrimmedResponse( $rawResponse ) { |
145 | | - |
| 90 | + function getFormattedResponse( $rawResponse ) { |
| 91 | + $nvString = $this->stripNameValueResponseHeaders( $rawResponse ); |
| 92 | + |
| 93 | + // prepare NVP response for sorting and outputting |
| 94 | + $responseArray = array( ); |
| 95 | + |
| 96 | + /** |
| 97 | + * The result response string looks like: |
| 98 | + * RESULT=7&PNREF=E79P2C651DC2&RESPMSG=Field format error&HOSTCODE=10747&DUPLICATE=1 |
| 99 | + * We want to turn this into an array of key value pairs, so explode on '&' and then |
| 100 | + * split up the resulting strings into $key => $value |
| 101 | + */ |
| 102 | + $result_arr = explode( "&", $nvString ); |
| 103 | + foreach ( $result_arr as $result_pair ) { |
| 104 | + list( $key, $value ) = preg_split( "/=/", $result_pair ); |
| 105 | + $responseArray[$key] = $value; |
| 106 | + } |
| 107 | + |
| 108 | + self::log( "Here is the response as an array: " . print_r( $responseArray, true ) ); //I am apparently a huge fibber. |
| 109 | + return $responseArray; |
146 | 110 | } |
147 | 111 | |
148 | 112 | /** |
149 | 113 | * Parse the response to get the status. Not sure if this should return a bool, or something more... telling. |
150 | 114 | */ |
151 | 115 | function getResponseStatus( $response ) { |
152 | | - |
| 116 | + //this function is only supposed to make sure the communication was well-formed... |
| 117 | + if ( is_array( $response ) && array_key_exists( 'RESULT', $response ) ) { |
| 118 | + return true; |
| 119 | + } else { |
| 120 | + return false; |
| 121 | + } |
153 | 122 | } |
154 | 123 | |
155 | 124 | /** |
— | — | @@ -156,7 +125,51 @@ |
157 | 126 | * return a key/value array of codes (if they exist) and messages. |
158 | 127 | */ |
159 | 128 | function getResponseErrors( $response ) { |
160 | | - |
| 129 | + |
| 130 | + if ( is_array( $response ) && array_key_exists( 'RESULT', $response ) ) { |
| 131 | + $resultCode = $response['RESULT']; |
| 132 | + } else { |
| 133 | + return; |
| 134 | + } |
| 135 | + |
| 136 | + $errors = array( ); |
| 137 | + |
| 138 | + switch ( $resultCode ) { |
| 139 | + case '0': |
| 140 | + $errors['1'] = wfMsg( 'payflowpro_gateway-response-0' ); |
| 141 | + break; |
| 142 | + case '126': |
| 143 | + $errors['5'] = wfMsg( 'payflowpro_gateway-response-126-2' ); |
| 144 | + break; |
| 145 | + case '12': |
| 146 | + $errors['2'] = wfMsg( 'payflowpro_gateway-response-12' ); |
| 147 | + break; |
| 148 | + case '13': |
| 149 | + $errors['2'] = wfMsg( 'payflowpro_gateway-response-13' ); |
| 150 | + break; |
| 151 | + case '114': |
| 152 | + $errors['2'] = wfMsg( 'payflowpro_gateway-response-114' ); |
| 153 | + break; |
| 154 | + case '4': |
| 155 | + $errors['3'] = wfMsg( 'payflowpro_gateway-response-4' ); |
| 156 | + break; |
| 157 | + case '23': |
| 158 | + $errors['3'] = wfMsg( 'payflowpro_gateway-response-23' ); |
| 159 | + break; |
| 160 | + case '24': |
| 161 | + $errors['3'] = wfMsg( 'payflowpro_gateway-response-24' ); |
| 162 | + break; |
| 163 | + case '112': |
| 164 | + $errors['3'] = wfMsg( 'payflowpro_gateway-response-112' ); |
| 165 | + break; |
| 166 | + case '125': |
| 167 | + $errors['3'] = wfMsg( 'payflowpro_gateway-response-125-2' ); |
| 168 | + break; |
| 169 | + default: |
| 170 | + $errors['4'] = wfMsg( 'payflowpro_gateway-response-default' ); |
| 171 | + } |
| 172 | + |
| 173 | + return $errors; |
161 | 174 | } |
162 | 175 | |
163 | 176 | /** |
— | — | @@ -164,19 +177,12 @@ |
165 | 178 | * return a key/value array |
166 | 179 | */ |
167 | 180 | function getResponseData( $response ) { |
168 | | - |
| 181 | + if ( is_array( $response ) && !empty( $response ) ) { |
| 182 | + return $response; |
| 183 | + } |
169 | 184 | } |
170 | 185 | |
171 | 186 | /** |
172 | | - * Take the entire response string, and strip everything we don't care about. |
173 | | - * For instance: If it's XML, we only want correctly-formatted XML. Headers must be killed off. |
174 | | - * return a string. |
175 | | - */ |
176 | | - function getFormattedResponse( $rawResponse ) { |
177 | | - |
178 | | - } |
179 | | - |
180 | | - /** |
181 | 187 | * Actually do... stuff. Here. |
182 | 188 | * TODO: Better comment. |
183 | 189 | * Process the entire response gott'd by the last four functions. |
— | — | @@ -185,75 +191,16 @@ |
186 | 192 | |
187 | 193 | } |
188 | 194 | |
189 | | - function parseXMLResponse( $rawResponse ) { |
190 | | - //TODO: Something. |
191 | | - $rawXML = $this->stripResponseHeaders( $rawResponse ); |
192 | | - if ( $rawXML === false ) { |
193 | | - return false; |
194 | | - } else { |
195 | | - $rawXML = $this->formatXmlString( $rawXML ); |
196 | | - } |
197 | | - $realXML = new DomDocument( '1.0' ); |
198 | | - self::log( "Here is the Raw XML: " . $rawXML ); |
199 | | - $realXML->loadXML( trim( $rawXML ) ); |
200 | | - |
201 | | - $aok = true; |
202 | | - |
203 | | - //find the node specified by the transaction structure. |
204 | | - //TODO: Error handling, because: Ugh. |
205 | | - $result_structure = $this->transactions[$this->currentTransaction()]['result']; |
206 | | - if ( is_array( $result_structure ) ) { |
207 | | - foreach ( $result_structure as $key => $value ) { //should only be one. |
208 | | - foreach ( $realXML->getElementsByTagName( $key ) as $node ) { |
209 | | - if ( $value === 'value' ) { //...stupid. But it's 'value' as opposed to 'attribute' |
210 | | - if ( array_key_exists( $node->nodeValue, $this->return_value_map ) && $this->return_value_map[$node->nodeValue] !== true ) { |
211 | | - $aok = false; |
212 | | - } |
213 | | - } |
214 | | - if ( $value === 'attribute' ) { |
215 | | - //TODO: Figure this out. This should mean the key name of one array up, which sounds painful. |
216 | | - } |
217 | | - if ( is_array( $value ) ) { |
218 | | - //TODO: ...this is looking like a recursive deal, here. Again. So do that. |
219 | | - } |
220 | | - } |
221 | | - } |
222 | | - } |
223 | | - |
224 | | - //TODO: Make this... you know: abstracty. |
225 | | - if ( $aok === false ) { |
226 | | - foreach ( $realXML->getElementsByTagName( 'ERROR' ) as $node ) { |
227 | | - $errdata = ''; |
228 | | - foreach ( $node->childNodes as $childnode ) { |
229 | | - $errdata .= "\n" . $childnode->nodeName . " " . $childnode->nodeValue; |
230 | | -// if ($childnode->nodeName == "CODE"){ |
231 | | -// //Excellent place to deal with the particular codes if we want to. |
232 | | -// } |
233 | | - } |
234 | | - self::log( "ON NOES! ERROR: $errdata" ); |
235 | | - } |
236 | | - } else { |
237 | | - self::log( "Response OK" ); |
238 | | - } |
239 | | - |
240 | | - //TODO: The bit where you strip all the response data that we might want to save, toss it into an array, and hand it back. |
241 | | - //We need to be handing more back here than just the... success or failure. Things need to be processed! I mean, probably. |
242 | | - |
243 | | - |
244 | | - return $aok; |
| 195 | + function defineStagedVars() { |
| 196 | + //OUR field names. |
| 197 | + $this->staged_vars = array( |
| 198 | + 'card_num', |
| 199 | + ); |
245 | 200 | } |
246 | 201 | |
247 | | - function stripResponseHeaders( $rawResponse ) { |
248 | | - $xmlStart = strpos( $rawResponse, '<?xml' ); |
249 | | - if ( $xmlStart == false ) { //I totally saw this happen one time. No XML, just <RESPONSE>... |
250 | | - $xmlStart = strpos( $rawResponse, '<RESPONSE' ); |
251 | | - } |
252 | | - if ( $xmlStart == false ) { //Still false. Your Head Asplode. |
253 | | - self::log( "Wow, that was so messed up I couldn't even parse the response, so here's the thing in its entirety:\n" . $rawResponse ); |
254 | | - return false; |
255 | | - } |
256 | | - $justXML = substr( $rawResponse, $xmlStart ); |
257 | | - return $justXML; |
| 202 | + protected function stage_card_num( $type = 'request' ) { |
| 203 | + //I realize that the $type isn't used. Voodoo. |
| 204 | + $this->postdata['card_num'] = str_replace( ' ', '', $this->postdata['card_num'] ); |
258 | 205 | } |
259 | 206 | |
260 | 207 | } |
Index: branches/fundraising/extensions/DonationInterface/gateway_common/gateway.adapter.php |
— | — | @@ -233,6 +233,26 @@ |
234 | 234 | die( "getValue found NOTHING for $gateway_field_name, $transaction." ); |
235 | 235 | } |
236 | 236 | |
| 237 | + function buildRequestNameValueString() { |
| 238 | + $structure = $this->transactions[$this->currentTransaction()]['request']; |
| 239 | + if ( !is_array( $structure ) ) { |
| 240 | + return ''; |
| 241 | + } |
| 242 | + |
| 243 | + $queryvals = array( ); |
| 244 | + |
| 245 | + //we are going to assume a flat array, because... namevalue. |
| 246 | + foreach ( $structure as $fieldname ) { |
| 247 | + $fieldvalue = $this->getValue( $fieldname ); |
| 248 | + if ( $fieldvalue !== '' && $fieldvalue !== false ) { |
| 249 | + $queryvals[] = $fieldname . '[' . strlen( $fieldvalue ) . ']=' . $fieldvalue; |
| 250 | + } |
| 251 | + } |
| 252 | + |
| 253 | + $ret = implode( '&', $queryvals ); |
| 254 | + return $ret; |
| 255 | + } |
| 256 | + |
237 | 257 | function buildRequestXML() { |
238 | 258 | $this->xmlDoc = new DomDocument( '1.0' ); |
239 | 259 | $node = $this->xmlDoc->createElement( 'XML' ); |
— | — | @@ -305,9 +325,11 @@ |
306 | 326 | |
307 | 327 | if ( $this->getCommunicationType() === 'namevalue' ) { |
308 | 328 | $namevalue = $this->postdata; |
309 | | - $this->getStopwatch( __FUNCTION__ ); |
310 | | - $returned = $this->curl_transaction( $namevalue ); |
311 | | - $this->saveCommunicationStats(); |
| 329 | + //buildRequestNameValueString() |
| 330 | + $this->getStopwatch( "buildRequestNameValueString" ); |
| 331 | + $namevalstring = $this->buildRequestNameValueString(); |
| 332 | + $this->saveCommunicationStats( "buildRequestNameValueString", $transaction ); |
| 333 | + $returned = $this->curl_transaction( $namevalstring ); |
312 | 334 | //put the response in a universal form, and return it. |
313 | 335 | } |
314 | 336 | |
— | — | @@ -405,7 +427,11 @@ |
406 | 428 | $headers = $this->getCurlBaseHeaders(); |
407 | 429 | $headers[] = 'Content-Length: ' . strlen( $data ); |
408 | 430 | |
409 | | - self::log( "Sending Data: " . $this->formatXmlString( $data ) ); |
| 431 | + if ( $this->getCommunicationType() === 'xml' ) { |
| 432 | + self::log( "Sending Data: " . $this->formatXmlString( $data ) ); |
| 433 | + } else { |
| 434 | + self::log( "Sending Data: " . $data ); |
| 435 | + } |
410 | 436 | |
411 | 437 | $curl_opts = $this->getCurlBaseOpts(); |
412 | 438 | $curl_opts[CURLOPT_HTTPHEADER] = $headers; |
— | — | @@ -466,6 +492,11 @@ |
467 | 493 | return $justXML; |
468 | 494 | } |
469 | 495 | |
| 496 | + function stripNameValueResponseHeaders( $rawResponse ) { |
| 497 | + $result = strstr( $rawResponse, 'RESULT' ); |
| 498 | + return $result; |
| 499 | + } |
| 500 | + |
470 | 501 | public static function log( $msg, $log_level=LOG_INFO ) { |
471 | 502 | $identifier = self::getIdentifier() . "_gateway"; |
472 | 503 | |