Katie Horn has uploaded a new change for review.
https://gerrit.wikimedia.org/r/165902
Change subject: Worldpay cleanup: Antifraud filters firing too much
......................................................................
Worldpay cleanup: Antifraud filters firing too much
Nutshell: The antifraud filters were firing on transactions
that were refused at the gateway. This was wasting bandwidth
and minfraud queries, and causing false positives in the ip
velocity filter.
Conflicts:
tests/Adapter/WorldPay/WorldPayTestCase.php
Change-Id: Ib20694516851a8cebc23a29887d32839a46ed430
---
M gateway_common/gateway.adapter.php
M worldpay_gateway/worldpay.adapter.php
2 files changed, 388 insertions(+), 336 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/DonationInterface
refs/changes/02/165902/1
diff --git a/gateway_common/gateway.adapter.php
b/gateway_common/gateway.adapter.php
index 650316f..ee73bff 100644
--- a/gateway_common/gateway.adapter.php
+++ b/gateway_common/gateway.adapter.php
@@ -31,12 +31,12 @@
/**
* Parse the response to get the errors in a format we can log and
otherwise deal with.
- * return a key/value array of codes (if they exist) and messages.
+ * return a key/value array of codes (if they exist) and messages.
*/
function getResponseErrors( $response );
/**
- * Harvest the data we need back from the gateway.
+ * Harvest the data we need back from the gateway.
* return a key/value array
*/
function getResponseData( $response );
@@ -53,20 +53,20 @@
public function processResponse( $response, &$retryVars = null );
/**
- * Should be a list of our variables that need special staging.
+ * Should be a list of our variables that need special staging.
* @see $this->staged_vars
*/
function defineStagedVars();
/**
- * defineTransactions will define the $transactions array.
- * The array will contain everything we need to know about the request
structure for all the transactions we care about,
- * for the current gateway.
- * First array key: Some way for us to id the transaction. Doesn't
actually have to be the gateway's name for it, but I'm going with that until I
have a reason not to.
- * Second array key:
- * 'request' contains the structure of that request.
Leaves in the array tree will eventually be mapped to actual values of ours,
- * according to the precidence established in the
getTransactionSpecificValue function.
- * 'values' contains default values for the transaction.
Things that are typically not overridden should go here.
+ * defineTransactions will define the $transactions array.
+ * The array will contain everything we need to know about the request
structure for all the transactions we care about,
+ * for the current gateway.
+ * First array key: Some way for us to id the transaction. Doesn't
actually have to be the gateway's name for it, but I'm going with that until I
have a reason not to.
+ * Second array key:
+ * 'request' contains the structure of that request.
Leaves in the array tree will eventually be mapped to actual values of ours,
+ * according to the precidence established in the
getTransactionSpecificValue function.
+ * 'values' contains default values for the transaction.
Things that are typically not overridden should go here.
*/
function defineTransactions();
@@ -75,9 +75,9 @@
function defineErrorMap();
/**
- * defineVarMap needs to set up the $var_map array.
+ * defineVarMap needs to set up the $var_map array.
* Keys = the name (or node name) value in the gateway transaction
- * Values = the mediawiki field name for the corresponding piece of
data.
+ * Values = the mediawiki field name for the corresponding piece of
data.
*/
function defineVarMap();
@@ -86,16 +86,16 @@
function defineDataConstraints();
/**
- * defineAccountInfo needs to set up the $accountInfo array.
+ * defineAccountInfo needs to set up the $accountInfo array.
* Keys = the name (or node name) value in the gateway transaction
- * Values = The actual values for those keys. Probably have to access a
global or two. (use getGlobal()!)
+ * Values = The actual values for those keys. Probably have to access a
global or two. (use getGlobal()!)
*/
function defineAccountInfo();
/**
* defineReturnValueMap sets up the $return_value_map array.
* Keys = The different constants that may be contained as values in
the gateway's response.
- * Values = what that string constant means to mediawiki.
+ * Values = what that string constant means to mediawiki.
*/
function defineReturnValueMap();
@@ -186,7 +186,7 @@
* @var array $error_map
*/
protected $error_map = array();
-
+
/**
* @see GatewayAdapter::defineGoToThankYouOn()
*
@@ -232,15 +232,15 @@
protected $unstaged_data;
protected $xmlDoc;
protected $dataObj;
-
+
/**
* $transaction_results is the member var that keeps track of the
results of
- * the latest discrete transaction with the gateway.
- * There could be multiple transaction with the gateway in any one
donation.
+ * the latest discrete transaction with the gateway.
+ * There could be multiple transaction with the gateway in any one
donation.
* Expected keys:
- * - 'status' => boolean, denoting if there were internal errors on our
end,
- * or at the gateway.
- * - 'message' => Originally supposed to be an i18n label, but
somewhere
+ * - 'status' => boolean, denoting if there were internal errors on our
end,
+ * or at the gateway.
+ * - 'message' => Originally supposed to be an i18n label, but somewhere
* along the line this just turned into a message that would be
marginally
* okay to display to a user.
* - 'errors' => An array of error codes => error messages that are
meant to
@@ -254,7 +254,7 @@
* failure of the transaction. Not widely used.
* - 'gateway_txn_id' - the gateway transaction ID
* - 'data' - All PARSED transaction data.
- * * @var type
+ * * @var type
*/
protected $transaction_results;
protected $validation_errors;
@@ -262,10 +262,10 @@
protected $current_transaction;
protected $action;
protected $risk_score = 0;
- public $debugarray;
+ public $debugarray;
/**
- * A boolean that will tell us if we've posted to ourselves. A little
more telling than
- * $wgRequest->wasPosted(), as something else could have posted to us.
+ * A boolean that will tell us if we've posted to ourselves. A little
more telling than
+ * $wgRequest->wasPosted(), as something else could have posted to us.
* @var boolean
*/
public $posted = false;
@@ -277,19 +277,19 @@
*/
protected static $globalsCache = array ( );
- //ALL OF THESE need to be redefined in the children. Much voodoo
depends on the accuracy of these constants.
+ //ALL OF THESE need to be redefined in the children. Much voodoo
depends on the accuracy of these constants.
const GATEWAY_NAME = 'Donation Gateway';
const IDENTIFIER = 'donation';
- const GLOBAL_PREFIX = 'wgDonationGateway'; //...for example.
+ const GLOBAL_PREFIX = 'wgDonationGateway'; //...for example.
public $communication_type = 'xml'; //this needs to be either 'xml' or
'namevalue'
public $redirect = FALSE;
public $log_outbound = FALSE; //This should be set to true for gateways
that don't return the request in the response. @see buildLogXML()
protected $valid_statuses = array(
- 'complete',
- 'pending',
- 'pending-poke',
- 'failed',
+ 'complete',
+ 'pending',
+ 'pending-poke',
+ 'failed',
'revised',
);
@@ -298,7 +298,7 @@
*
*/
public function getGoToThankYouOn() {
-
+
return $this->goToThankYouOn;
}
@@ -331,7 +331,7 @@
$this->url = self::getGlobal( 'TestingURL' );
}
- //so we know we can skip all the visual stuff.
+ //so we know we can skip all the visual stuff.
if ( $options['api_request'] ) {
$this->setApiRequest();
}
@@ -345,7 +345,7 @@
$this->unstaged_data = $this->dataObj->getDataEscaped();
$this->staged_data = $this->unstaged_data;
-
+
//checking to see if we have an edit token in the request...
$this->posted = ( $this->dataObj->wasPosted() && (!is_null(
$wgRequest->getVal( 'token', null ) ) ) );
@@ -392,15 +392,15 @@
* always have less stale data (and we need messages to come out of
* there before data exists here)
*
- * @return string
+ * @return string
*/
public function getLogMessagePrefix() {
return $this->dataObj->getLogMessagePrefix();
}
/**
- * getThankYouPage should either return a full page url, or false.
- * @return mixed Page URL in string format, or false if none is set.
+ * getThankYouPage should either return a full page url, or false.
+ * @return mixed Page URL in string format, or false if none is set.
*/
public function getThankYouPage() {
$page = self::getGlobal( "ThankYouPage" );
@@ -411,8 +411,8 @@
}
/**
- * getFailPage should either return a full page url, or false.
- * @return mixed Page URL in string format, or false if none is set.
+ * getFailPage should either return a full page url, or false.
+ * @return mixed Page URL in string format, or false if none is set.
*/
public function getFailPage() {
//Prefer RapidFail.
@@ -437,14 +437,14 @@
}
return $page;
}
-
+
/**
- * For pages we intend to redirect to. This function will take either a
full
- * URL or a page title, and turn it into a URL with the appropriate
language
- * appended onto the end.
- * @param string $url Either a wiki page title, or a URL to an external
wiki
- * page title.
- * @return string A URL
+ * For pages we intend to redirect to. This function will take either a
full
+ * URL or a page title, and turn it into a URL with the appropriate
language
+ * appended onto the end.
+ * @param string $url Either a wiki page title, or a URL to an external
wiki
+ * page title.
+ * @return string A URL
*/
protected function appendLanguageAndMakeURL( $url ){
$language = $this->getData_Unstaged_Escaped( 'language' );
@@ -453,8 +453,8 @@
if ( !is_array($dirs) || !in_array( $language, $dirs ) ){
$url = $url . "/$language";
}
-
- if ( strpos( $url, 'http' ) === 0) {
+
+ if ( strpos( $url, 'http' ) === 0) {
return $url;
} else { //this isn't a url yet.
$returnTitle = Title::newFromText( $url );
@@ -464,12 +464,12 @@
}
/**
- * Checks the edit tokens in the user's session against the one
gathered
- * from populated form data.
- * Adds a string to the debugarray, to make it a little easier to tell
what
+ * Checks the edit tokens in the user's session against the one gathered
+ * from populated form data.
+ * Adds a string to the debugarray, to make it a little easier to tell
what
* happened if we turn the debug results on.
* Only called from the .body pages
- * @return boolean true if match, else false.
+ * @return boolean true if match, else false.
*/
public function checkTokens() {
$checkResult = $this->token_checkTokens();
@@ -483,13 +483,13 @@
$this->refreshGatewayValueFromSource( 'token' );
return $checkResult;
}
-
+
/**
- * Returns staged data from the adapter object, or null if a key was
- * specified and no value exsits.
- * @param string $val An optional specific key you want returned.
- * @return mixed All the staged data held by the adapter, or if a key
was
- * set, the staged value for that key.
+ * Returns staged data from the adapter object, or null if a key was
+ * specified and no value exsits.
+ * @param string $val An optional specific key you want returned.
+ * @return mixed All the staged data held by the adapter, or if a key
was
+ * set, the staged value for that key.
*/
protected function getData_Staged( $val = '' ) {
if ( $val === '' ) {
@@ -502,7 +502,7 @@
}
}
}
-
+
/**
* A helper function to let us stash extra data after the form has
been submitted.
*
@@ -516,15 +516,15 @@
$calculated_fields = $this->dataObj->getCalculatedFields();
$data_fields = array_keys( $dataArray );
$data_fields = array_merge( $data_fields, $calculated_fields );
-
+
foreach ( $data_fields as $value){
$this->refreshGatewayValueFromSource( $value );
}
-
- //and now check to see if you have to re-stage.
- //I'd fire off individual staging functions by value, but
that's a
- //really bad idea, as multiple staged vars could be used in any
staging
- //function, to calculate any other staged var.
+
+ //and now check to see if you have to re-stage.
+ //I'd fire off individual staging functions by value, but
that's a
+ //really bad idea, as multiple staged vars could be used in any
staging
+ //function, to calculate any other staged var.
$changed_staged_vars = array_intersect( $this->staged_vars,
$data_fields );
if ( count( $changed_staged_vars ) ) {
$this->stageData( $pipelineStage );
@@ -532,19 +532,19 @@
}
/**
- * This is the ONLY getData type function anything should be using
- * outside the adapter.
- * Short explanation of the data population up to now:
- * *) When the gateway adapter is constructed, it constructs a
DonationData
+ * This is the ONLY getData type function anything should be using
+ * outside the adapter.
+ * Short explanation of the data population up to now:
+ * *) When the gateway adapter is constructed, it constructs a
DonationData
* object.
- * *) On construction, the DonationData object pulls donation data
from an
+ * *) On construction, the DonationData object pulls donation data
from an
* appropriate source, and normalizes the entire data set
for storage.
- * *) The gateway adapter pulls normalized, html escaped data out
of the
- * DonationData object, as the base of its own data set.
+ * *) The gateway adapter pulls normalized, html escaped data out
of the
+ * DonationData object, as the base of its own data set.
* @param string $val The specific key you're looking for (if any)
- * @return mixed An array of all the raw, unstaged (but normalized and
- * sanitized) data sent to the adapter, or if $val was set, either the
- * specific value held for $val, or null if none exists.
+ * @return mixed An array of all the raw, unstaged (but normalized and
+ * sanitized) data sent to the adapter, or if $val was set, either the
+ * specific value held for $val, or null if none exists.
*/
public function getData_Unstaged_Escaped( $val = '' ) {
if ( $val === '' ) {
@@ -559,25 +559,25 @@
}
/**
- * This function is important.
- * All the globals in Donation Interface should be accessed in this
manner
- * if they are meant to have a default value, but can be overridden by
any
- * of the gateways. It will check to see if a gateway-specific global
- * exists, and if one is not set, it will pull the default from the
- * wgDonationInterface definitions. Through this function, it is no
longer
- * necessary to define gateway-specific globals in LocalSettings unless
you
- * wish to override the default value for all gateways.
+ * This function is important.
+ * All the globals in Donation Interface should be accessed in this
manner
+ * if they are meant to have a default value, but can be overridden by
any
+ * of the gateways. It will check to see if a gateway-specific global
+ * exists, and if one is not set, it will pull the default from the
+ * wgDonationInterface definitions. Through this function, it is no
longer
+ * necessary to define gateway-specific globals in LocalSettings unless
you
+ * wish to override the default value for all gateways.
* If the variable exists in {prefix}AccountInfo[currentAccountName],
* that value will override the default settings.
* Caches found values in self::$globalsCache
*
* @param string $varname The global value we're looking for. It will
first
- * look for a global named for the instantiated gateway's
GLOBAL_PREFIX,
- * plus the $varname value. If that doesn't come up with anything that
has
- * been set, it will use the default value for all of donation
interface,
- * stored in $wgDonationInterface . $varname.
- * @return mixed The configured value for that gateway if it exists. If
not,
- * the configured value for Donation Interface if it exists or not.
+ * look for a global named for the instantiated gateway's GLOBAL_PREFIX,
+ * plus the $varname value. If that doesn't come up with anything that
has
+ * been set, it will use the default value for all of donation
interface,
+ * stored in $wgDonationInterface . $varname.
+ * @return mixed The configured value for that gateway if it exists. If
not,
+ * the configured value for Donation Interface if it exists or not.
*/
static function getGlobal( $varname ) {
//adding another layer of depth here, in case you're working
with two gateways in the same request.
@@ -590,7 +590,7 @@
global $$globalname;
if ( !isset( $$globalname ) ) {
$globalname = "wgDonationInterface" . $varname;
- global $$globalname; //set or not. This is
fine.
+ global $$globalname; //set or not. This is fine.
}
self::$globalsCache[self::getGlobalPrefix()][$varname]
= $$globalname;
}
@@ -630,31 +630,31 @@
if ( is_null( $code ) ) {
return $this->error_map;
}
-
+
$defaults = array(
'translate' => false,
);
$options = array_merge( $defaults, $options );
$response_message = $this->getIdentifier() .
'_gateway-response-' . $code;
-
+
$translatedMessage = WmfFramework::formatMessage(
$response_message );
-
+
// Check to see if an error message exists in translation
if ( substr( $translatedMessage, 0, 3 ) !== '<' ) {
-
+
// Message does not exist
$translatedMessage = '';
}
-
+
// If the $code does not exist, use the default code: 0
$code = !isset( $this->error_map[ $code ] ) ? 0 : $code;
-
+
$translatedMessage = ( $options['translate'] && empty(
$translatedMessage ) ) ? WmfFramework::formatMessage( $this->error_map[$code] )
: $translatedMessage;
// Check to see if we return the translated message.
$message = ( $options['translate'] ) ? $translatedMessage :
$this->error_map[ $code ];
-
+
return $message;
}
@@ -668,7 +668,7 @@
* @return string Returns the translated message from @see
GatewayAdapter::$error_map
*/
public function getErrorMapByCodeAndTranslate( $code ) {
-
+
return $this->getErrorMap( $code, array( 'translate' => true, )
);
}
@@ -703,7 +703,7 @@
$this->log( $msg, LOG_CRIT );
throw new MWException( $msg );
}
- //Ensures we are using the correct transaction structure for
our various lookups.
+ //Ensures we are using the correct transaction structure for
our various lookups.
$transaction = $this->getCurrentTransaction();
if ( !$transaction ){
@@ -727,12 +727,12 @@
//If there's a value in the post data (name-translated by the
var_map), use that.
if ( array_key_exists( $gateway_field_name, $this->var_map ) ) {
- if ( $token === true ) { //we just want the field name
to use, so short-circuit all that mess.
+ if ( $token === true ) { //we just want the field name
to use, so short-circuit all that mess.
return '@' .
$this->var_map[$gateway_field_name];
}
$staged = $this->getData_Staged(
$this->var_map[$gateway_field_name] );
if ( !is_null( $staged ) ) {
- //if it was sent, use that.
+ //if it was sent, use that.
return $staged;
} else {
//return the default for that form value
@@ -745,8 +745,8 @@
}
}
- //not in the map, or hard coded. What then?
- //Complain furiously, for your code is faulty.
+ //not in the map, or hard coded. What then?
+ //Complain furiously, for your code is faulty.
$msg = self::getGatewayName() . ': Requested value ' .
$gateway_field_name . ' cannot be found in the transactions structure.';
$this->log( $msg, LOG_CRIT );
throw new MWException( $msg );
@@ -776,15 +776,15 @@
return $this->transactions[$transaction]['request'];
}
-
+
/**
* Builds a set of transaction data in name/value format
* *)The current transaction must be set before you call
this function.
- * *)Uses getTransactionSpecificValue to assign staged
values to the
- * fields required by the gateway. Look there for more insight into the
- * heirarchy of all possible data sources.
- * @return string The raw transaction in name/value format, ready to be
- * curl'd off to the remote server.
+ * *)Uses getTransactionSpecificValue to assign staged
values to the
+ * fields required by the gateway. Look there for more insight into the
+ * heirarchy of all possible data sources.
+ * @return string The raw transaction in name/value format, ready to be
+ * curl'd off to the remote server.
*/
protected function buildRequestNameValueString() {
// Look up the request structure for our current transaction
type in the transactions array
@@ -795,7 +795,7 @@
$queryvals = array();
- //we are going to assume a flat array, because... namevalue.
+ //we are going to assume a flat array, because... namevalue.
foreach ( $structure as $fieldname ) {
$fieldvalue = $this->getTransactionSpecificValue(
$fieldname );
if ( $fieldvalue !== '' && $fieldvalue !== false ) {
@@ -810,11 +810,11 @@
/**
* Builds a set of transaction data in XML format
* *)The current transaction must be set before you call
this function.
- * *)(eventually) uses getTransactionSpecificValue to
assign staged
- * values to the fields required by the gateway. Look there for more
insight
- * into the heirarchy of all possible data sources.
- * @return string The raw transaction in xml format, ready to be
- * curl'd off to the remote server.
+ * *)(eventually) uses getTransactionSpecificValue to
assign staged
+ * values to the fields required by the gateway. Look there for more
insight
+ * into the heirarchy of all possible data sources.
+ * @return string The raw transaction in xml format, ready to be
+ * curl'd off to the remote server.
*/
protected function buildRequestXML( $rootElement = 'XML', $encoding =
'UTF-8' ) {
$this->xmlDoc = new DomDocument( '1.0', $encoding );
@@ -844,7 +844,7 @@
$this->xmlDoc->appendChild( $log_node );
$logme = $this->xmlDoc->saveXML();
} else {
- //...safe zone.
+ //...safe zone.
$logme = $return;
}
$this->log( $message . $logme );
@@ -855,22 +855,22 @@
}
/**
- * buildRequestXML helper function.
- * Builds the XML transaction by recursively crawling the transaction
- * structure and adding populated nodes by reference.
- * @param array $structure Current transaction's more leafward
structure,
- * from the point of view of the current XML node.
- * @param xmlNode $node The current XML node.
+ * buildRequestXML helper function.
+ * Builds the XML transaction by recursively crawling the transaction
+ * structure and adding populated nodes by reference.
+ * @param array $structure Current transaction's more leafward
structure,
+ * from the point of view of the current XML node.
+ * @param xmlNode $node The current XML node.
* @param bool $js More likely cruft relating back to
buildTransactionFormat
*/
protected function buildTransactionNodes( $structure, &$node, $js =
false ) {
- if ( !is_array( $structure ) ) { //this is a weird case that
shouldn't ever happen. I'm just being... thorough. But, yeah: It's like... the
base-1 case.
+ if ( !is_array( $structure ) ) { //this is a weird case that
shouldn't ever happen. I'm just being... thorough. But, yeah: It's like... the
base-1 case.
$this->appendNodeIfValue( $structure, $node, $js );
} else {
foreach ( $structure as $key => $value ) {
if ( !is_array( $value ) ) {
- //do not use $key. $key is meaningless
in this case.
+ //do not use $key. $key is meaningless
in this case.
$this->appendNodeIfValue( $value,
$node, $js );
} else {
$keynode =
$this->xmlDoc->createElement( $key );
@@ -879,7 +879,7 @@
}
}
}
- //not actually returning anything. It's all side-effects.
Because I suck like that.
+ //not actually returning anything. It's all side-effects.
Because I suck like that.
}
/**
@@ -904,16 +904,16 @@
}
/**
- * appendNodeIfValue is a helper function for buildTransactionNodes,
which
- * is used by buildRequestXML to construct an XML transaction.
- * This function will append an XML node to the transaction being built
via
- * the passed-in parent node, only if the current node would have a
- * non-empty value.
- * @param string $value The GATEWAY's field name for the current node.
+ * appendNodeIfValue is a helper function for buildTransactionNodes,
which
+ * is used by buildRequestXML to construct an XML transaction.
+ * This function will append an XML node to the transaction being built
via
+ * the passed-in parent node, only if the current node would have a
+ * non-empty value.
+ * @param string $value The GATEWAY's field name for the current node.
* @param string $node The parent node this node will be contained in,
if it
- * is determined to have a non-empty value.
- * @param bool $js Probably cruft at this point. This is connected to
the
- * function buildTransactionFormat.
+ * is determined to have a non-empty value.
+ * @param bool $js Probably cruft at this point. This is connected to
the
+ * function buildTransactionFormat.
*/
protected function appendNodeIfValue( $value, &$node, $js = false ) {
$nodevalue = $this->getTransactionSpecificValue( $value, $js );
@@ -962,7 +962,7 @@
$this->log( "Failed Validation. Aborting $transaction "
. print_r( $this->getValidationErrors(), true ) );
return $return;
}
-
+
$retryCount = 0;
do {
@@ -1042,7 +1042,7 @@
return $this->getTransactionAllResults();
}
- //TODO: Maybe move this to the pre_process functions?
+ //TODO: Maybe move this to the pre_process functions?
$this->dataObj->saveContributionTrackingData();
$commType = $this->getCommunicationType();
@@ -1084,7 +1084,7 @@
),
'action' => $this->getValidationAction(),
));
-
+
return $this->getTransactionAllResults();
}
@@ -1139,12 +1139,17 @@
$this->setTransactionResult(
$this->getValidationAction(), 'action' );
}
- //If we have any special post-process instructions for this
- //transaction, do 'em.
- //NOTE: If you want your transaction to fire off the
post-process
- //hooks, you need to run $this->runPostProcessHooks in a
function
- //called
- // 'post_process' . strtolower($transaction)
+ //if we have set errors by this point, the transaction is not
okay
+ $errors = $this->getTransactionErrors();
+ if ( !empty( $errors ) ) {
+ $txn_ok = false;
+ }
+ //If we have any special post-process instructions for this
+ //transaction, do 'em.
+ //NOTE: If you want your transaction to fire off the
post-process
+ //hooks, you need to run $this->runPostProcessHooks in a
function
+ //called
+ // 'post_process' . strtolower($transaction)
//in the appropriate gateway object.
if ( $txn_ok && empty( $retryVars ) ) {
$this->executeIfFunctionExists( 'post_process_' .
$transaction );
@@ -1173,9 +1178,9 @@
}
function getCurlBaseOpts() {
- //I chose to return this as a function so it's easy to
override.
+ //I chose to return this as a function so it's easy to override.
//TODO: probably this for all the junk I currently have stashed
in the constructor.
- //...maybe.
+ //...maybe.
$opts = array(
CURLOPT_URL => $this->url,
CURLOPT_USERAGENT => WmfFramework::getUserAgent(),
@@ -1237,12 +1242,12 @@
}
/**
- * Gets the currently set transaction name. This value should only ever
be
- * set with setCurrentTransaction: A function that ensures the current
- * transaction maps to a first-level key that is known to exist in the
- * $transactions array, defined in the child gateway.
- * @return mixed The name of the properly set transaction, or false if
none
- * has been set.
+ * Gets the currently set transaction name. This value should only ever
be
+ * set with setCurrentTransaction: A function that ensures the current
+ * transaction maps to a first-level key that is known to exist in the
+ * $transactions array, defined in the child gateway.
+ * @return mixed The name of the properly set transaction, or false if
none
+ * has been set.
*/
public function getCurrentTransaction(){
if ( is_null( $this->current_transaction ) ) {
@@ -1298,14 +1303,14 @@
}
/**
- * Sends a curl request to the gateway server, and gets a response.
+ * Sends a curl request to the gateway server, and gets a response.
* Saves that response to the gateway object with
setTransactionResult();
- * @param string $data the raw data we want to curl up to a server
somewhere.
- * Should have been constructed with either
buildRequestNameValueString, or
- * buildRequestXML.
- * @return boolean true if the communication was successful and there
is a
- * parseable response, false if there was a fundamental communication
- * problem. (timeout, bad URL, etc.)
+ * @param string $data the raw data we want to curl up to a server
somewhere.
+ * Should have been constructed with either
buildRequestNameValueString, or
+ * buildRequestXML.
+ * @return boolean true if the communication was successful and there
is a
+ * parseable response, false if there was a fundamental communication
+ * problem. (timeout, bad URL, etc.)
*/
protected function curl_transaction( $data ) {
// assign header data necessary for the curl_setopt() function
@@ -1316,7 +1321,7 @@
$gatewayName = self::getGatewayName();
$email = $this->getData_Unstaged_Escaped( 'email' );
-
+
/**
* This log line is pretty important. Usually when a donor
contacts us
* saying that they have experienced problems donating, the
first thing
@@ -1505,7 +1510,7 @@
/**
* Log messages out to syslog (if configured), or the wfDebugLog
* @param string $msg The message to log
- * @param int $log_level Should be one of the following:
+ * @param int $log_level Should be one of the following:
* * LOG_EMERG - Actual meltdown in progress: Get everyone.
* * LOG_ALERT - Time to start paging people and failing things
over
* * LOG_CRIT - Corrective action required, but you probably have
some time.
@@ -1513,8 +1518,8 @@
* * LOG_WARNING - Not good, but will require eventual action to
preserve stability
* * LOG_NOTICE - Unusual circumstances, but nothing imediately
alarming
* * LOG_INFO - Nothing to see here. Business as usual.
- * * LOG_DEBUG - Probably shouldn't use these unless we're in the
process
- * of diagnosing a relatively esoteric problem that only happens in the
prod
+ * * LOG_DEBUG - Probably shouldn't use these unless we're in the
process
+ * of diagnosing a relatively esoteric problem that only happens in the
prod
* environment, which will require a settings change to start the data
avalanche.
* @param string $log_id_suffix Primarily used for shunting syslog
messages off into alternative buckets.
* @return null
@@ -1590,7 +1595,7 @@
$line = str_pad( $token, strlen( $token ) + $pad, ' ',
STR_PAD_LEFT );
$result .= $line . "\n"; // add to the cumulative
result, with linefeed
$token = strtok( "\n" ); // get the next token
- $pad += $indent; // update the pad size for subsequent
lines
+ $pad += $indent; // update the pad size for subsequent
lines
endwhile;
return $result;
@@ -1626,15 +1631,15 @@
}
/**
- * getStopwatch keeps track of how long things take, for logging,
- * output, determining if we should loop on some method again...
whatever.
- * @staticvar array $start The microtime at which a stopwatch was
started.
- * @param string $string Some identifier for each stopwatch value we
want to
+ * getStopwatch keeps track of how long things take, for logging,
+ * output, determining if we should loop on some method again...
whatever.
+ * @staticvar array $start The microtime at which a stopwatch was
started.
+ * @param string $string Some identifier for each stopwatch value we
want to
* keep. Each unique $string passed in will get its own value in $start.
- * @param bool $reset If this is set to true, it will reset any $start
value
- * recorded for the $string identifier.
- * @return numeric The difference in microtime (rounded to 4 decimal
places)
- * between the $start value, and now.
+ * @param bool $reset If this is set to true, it will reset any $start
value
+ * recorded for the $string identifier.
+ * @return numeric The difference in microtime (rounded to 4 decimal
places)
+ * between the $start value, and now.
*/
public function getStopwatch( $string, $reset = false ) {
static $start = array();
@@ -1650,13 +1655,13 @@
/**
*
- * @param string $function This is the function name that identifies
the
- * stopwatch that should have already been started with the
getStopwatch
+ * @param string $function This is the function name that identifies the
+ * stopwatch that should have already been started with the getStopwatch
* function.
- * @param string $additional Additional information about the thing
we're
- * currently timing. Meant to be easily searchable.
- * @param string $vars Intended to be particular values of any
variables
- * that might be of interest.
+ * @param string $additional Additional information about the thing
we're
+ * currently timing. Meant to be easily searchable.
+ * @param string $vars Intended to be particular values of any variables
+ * that might be of interest.
*/
public function saveCommunicationStats( $function = '', $additional =
'', $vars = '' ) {
static $saveStats = null;
@@ -1665,11 +1670,11 @@
if ( $saveStats === null ){
$saveStats = self::getGlobal( 'SaveCommStats' );
}
-
+
if ( !$saveStats ){
return;
}
-
+
if ( $saveDB === null ){
$db =
ContributionTrackingProcessor::contributionTrackingConnection();
if ( $db->tableExists( 'communication_stats' ) ) {
@@ -1678,7 +1683,7 @@
$saveDB = false;
}
}
-
+
$params = array(
'contribution_id' => $this->getData_Unstaged_Escaped(
'contribution_tracking_id' ),
'duration' => $this->getStopwatch( $function ),
@@ -1687,13 +1692,13 @@
'vars' => $vars,
'additional' => $additional,
);
-
- if ( $saveDB ){
+
+ if ( $saveDB ){
$db =
ContributionTrackingProcessor::contributionTrackingConnection();
$params['ts'] = $db->timestamp();
$db->insert( 'communication_stats', $params );
} else {
- //save to syslog. But which syslog?
+ //save to syslog. But which syslog?
$msg = '';
foreach ($params as $key=>$val){
$msg .= "$key:$val - ";
@@ -1755,32 +1760,32 @@
public function findCodeAction( $transaction, $key, $code ) {
$this->getStopwatch( __FUNCTION__, true );
-
+
// Do not allow anything that is not numeric
if ( !is_numeric( $code ) ) {
return null;
}
// Cast the code as an integer
- settype( $code, 'integer');
-
+ settype( $code, 'integer');
+
// Check to see if the transaction is defined
if ( !array_key_exists( $transaction, $this->return_value_map )
) {
return null;
}
-
- // Verify the key exists within the transaction
+
+ // Verify the key exists within the transaction
if ( !array_key_exists( $key, $this->return_value_map[
$transaction ] ) || !is_array( $this->return_value_map[ $transaction ][ $key ]
) ) {
return null;
}
-
- //sort the array so we can do this quickly.
+
+ //sort the array so we can do this quickly.
ksort( $this->return_value_map[ $transaction ][ $key ],
SORT_NUMERIC );
$ranges = $this->return_value_map[ $transaction ][ $key ];
//so, you have a code, which is a number. You also have a
numerically sorted array.
//loop through until you find an upper >= your code.
- //make sure it's in the range, and return the action.
+ //make sure it's in the range, and return the action.
foreach ( $ranges as $upper => $val ) {
if ( $upper >= $code ) { //you've arrived. It's either
here or it's nowhere.
if ( is_array( $val ) ) {
@@ -1803,18 +1808,18 @@
}
/**
- * Saves a stomp frame to the configured server and queue, based on the
- * outcome of our current transaction.
- * The big tricky thing here, is that we DO NOT SET a FinalStatus,
- * unless we have just learned what happened to a donation in progress,
- * through performing the current transaction.
- * To put it another way, getFinalStatus should always return
- * false, unless it's new data about a new transaction. In that case,
the
- * outcome will be assigned and the proper stomp hook selected.
- *
- * Probably called in runPostProcessHooks(), which is itself most
likely to
- * be called through executeFunctionIfExists, later on in
do_transaction.
- * @return null
+ * Saves a stomp frame to the configured server and queue, based on the
+ * outcome of our current transaction.
+ * The big tricky thing here, is that we DO NOT SET a FinalStatus,
+ * unless we have just learned what happened to a donation in progress,
+ * through performing the current transaction.
+ * To put it another way, getFinalStatus should always return
+ * false, unless it's new data about a new transaction. In that case,
the
+ * outcome will be assigned and the proper stomp hook selected.
+ *
+ * Probably called in runPostProcessHooks(), which is itself most
likely to
+ * be called through executeFunctionIfExists, later on in
do_transaction.
+ * @return null
*/
protected function doStompTransaction() {
if ( !$this->getGlobal( 'EnableStomp' ) ){
@@ -1849,23 +1854,23 @@
$this->log( "STOMP ERROR. Could not add message to
'{$queue}' queue: {$e->getMessage()} " . json_encode( $transaction ), LOG_CRIT
);
}
}
-
-
+
+
/**
- * Function that adds a stomp message to a special 'limbo' queue, for
data
- * that is either highly likely or completely guaranteed to be
bifurcated by
- * handing the ball to a third-party process.
+ * Function that adds a stomp message to a special 'limbo' queue, for
data
+ * that is either highly likely or completely guaranteed to be
bifurcated by
+ * handing the ball to a third-party process.
*
* @param bool $antiMessage If TRUE message will be formatted to
destroy a message in the limbo
* queue when the orphan slayer is run.
*
- * @return null
+ * @return null
*/
protected function doLimboStompTransaction( $antiMessage = false ) {
if ( !$this->getGlobal( 'EnableStomp' ) ){
return;
}
-
+
$this->debugarray[] = "Attempting Limbo Stomp Transaction!";
$transaction = $this->getStompTransaction( $antiMessage );
@@ -1965,15 +1970,15 @@
}
/**
- * Executes the specified function in $this, if one exists.
- * NOTE: THIS WILL LCASE YOUR FUNCTION_NAME.
- * ...I like to keep the voodoo functions tidy.
- * @param string $function_name The name of the function you're hoping
to
- * execute.
- * @param mixed $parameter That's right: For now you only get one.
+ * Executes the specified function in $this, if one exists.
+ * NOTE: THIS WILL LCASE YOUR FUNCTION_NAME.
+ * ...I like to keep the voodoo functions tidy.
+ * @param string $function_name The name of the function you're hoping
to
+ * execute.
+ * @param mixed $parameter That's right: For now you only get one.
*/
function executeIfFunctionExists( $function_name, $parameter = null ) {
- $function_name = strtolower( $function_name ); //Because,
that's why.
+ $function_name = strtolower( $function_name ); //Because,
that's why.
if ( method_exists( $this, $function_name ) ) {
$this->{$function_name}( $parameter );
}
@@ -1990,13 +1995,13 @@
$this->staged_data = $this->unstaged_data;
}
$this->defineStagedVars();
- //If we tried to piggyback off the same loop, all the vars
wouldn't be ready, and some staging functions will require
+ //If we tried to piggyback off the same loop, all the vars
wouldn't be ready, and some staging functions will require
//multiple variables.
foreach ( $this->staged_vars as $field ) {
$function_name = 'stage_' . $field;
$this->executeIfFunctionExists( $function_name, $type );
}
-
+
// Format the staged data
if ($type === 'request'){
$this->formatStagedData();
@@ -2016,25 +2021,25 @@
// Trim all values if they are a string
$value = is_string( $value ) ? trim( $value ) : $value;
-
+
if ( isset( $this->dataConstraints[ $field ] ) &&
is_string( $value ) ) {
-
+
// Truncate the field if it has a length
specified
if ( isset( $this->dataConstraints[ $field
]['length'] ) ) {
$length = (integer)
$this->dataConstraints[ $field ]['length'];
} else {
$length = false;
}
-
+
if ( !empty( $length ) && !empty( $value ) ) {
//Note: This is the very last resort.
This should already have been dealt with thoroughly in staging.
$value = substr( $value, 0, $length );
}
-
+
} else {
//$this->log( 'Field does not exist in
$this->dataConstraints[ ' . ( string ) $field . ' ]', LOG_DEBUG );
}
-
+
$this->staged_data[ $field ] = $value;
}
}
@@ -2105,7 +2110,7 @@
$queryparams = array();
- //we are going to assume a flat array, because... namevalue.
+ //we are going to assume a flat array, because... namevalue.
foreach ( $structure as $fieldname ) {
$fieldvalue = $this->getTransactionSpecificValue(
$fieldname );
if ( $fieldvalue !== '' && $fieldvalue !== false ) {
@@ -2143,13 +2148,13 @@
}
/**
- * SetTransactionResult sets the gateway adapter object's
- * $transaction_results value.
- * If a $key is specified, it only sets the specified key's value. If
no
+ * SetTransactionResult sets the gateway adapter object's
+ * $transaction_results value.
+ * If a $key is specified, it only sets the specified key's value. If no
* $key is specified, it resets the value of the entire array.
* @param mixed $value The value to set in $transaction_results
- * @param mixed $key Optional: A specific key to set, or false
(default) to
- * reset the entire result array.
+ * @param mixed $key Optional: A specific key to set, or false
(default) to
+ * reset the entire result array.
*/
public function setTransactionResult( $value = array(), $key = false ) {
if ( $key === false ) {
@@ -2160,7 +2165,7 @@
}
/**
- * Returns the 'result' key of $transaction_results, or false if none
is
+ * Returns the 'result' key of $transaction_results, or false if none is
* present
* @return mixed
*/
@@ -2173,8 +2178,8 @@
}
/**
- * Returns the 'status' key of $transaction_results, or false if none
is
- * present.
+ * Returns the 'status' key of $transaction_results, or false if none is
+ * present.
* @return mixed
*/
public function getTransactionStatus() {
@@ -2187,7 +2192,7 @@
/**
* If it has been set: returns the final payment status in the
- * $transaction_results array. This is the one we care about for
switching
+ * $transaction_results array. This is the one we care about for
switching
* on overall behavior. Otherwise, returns false.
* @return mixed Final Transaction results status, or false if not set.
* Possible valid statuses are: 'complete', 'pending', 'pending-poke',
'failed' and 'revised'.
@@ -2256,21 +2261,21 @@
$this->transaction_results['FINAL_STATUS'] = $status;
}
-
+
/**
* Easily-child-overridable log component of setting the final
* transaction status, which will only ever be set at the very end of a
* transaction workflow.
* @param type $status
*/
- public function logFinalStatus( $status ){
+ public function logFinalStatus( $status ){
$action = $this->getValidationAction();
$msg = " FINAL STATUS: '$status:$action' - ";
-
- //what do we want in here?
- //Attempted payment type, country of origin, $status, amount...
campaign?
- //error message if one exists.
+
+ //what do we want in here?
+ //Attempted payment type, country of origin, $status, amount...
campaign?
+ //error message if one exists.
$keys = array(
'payment_submethod',
'payment_method',
@@ -2279,16 +2284,16 @@
'amount',
'currency_code',
);
-
+
foreach ($keys as $key){
$msg .= $this->getData_Unstaged_Escaped( $key ) . ', ';
}
-
+
$txn_message = $this->getTransactionMessage();
if ( $txn_message ){
$msg .= " $txn_message";
}
-
+
$this->log( $msg, LOG_INFO, '_payment_init' );
}
@@ -2339,8 +2344,8 @@
}
/**
- * Returns the FORMATTED data harvested from the reply, or false if it
is not set.
- * @return mixed An array of returned data, or false.
+ * Returns the FORMATTED data harvested from the reply, or false if it
is not set.
+ * @return mixed An array of returned data, or false.
*/
public function getTransactionData() {
if ( array_key_exists( 'data', $this->transaction_results ) ) {
@@ -2351,13 +2356,13 @@
}
/**
- * Returns an array of errors, in the format $error_code =>
$error_message.
+ * Returns an array of errors, in the format $error_code =>
$error_message.
* This should be an empty array on transaction success.
*
* @return array
*/
public function getTransactionErrors() {
-
+
if ( is_array( $this->transaction_results ) &&
array_key_exists( 'errors', $this->transaction_results ) ) {
return $this->transaction_results['errors'];
} else {
@@ -2373,7 +2378,7 @@
return get_called_class();
}
- //only the gateway should be setting validation errors. Everybody else
should set manual errors.
+ //only the gateway should be setting validation errors. Everybody else
should set manual errors.
protected function setValidationErrors( $errors ) {
$this->validation_errors = $errors;
}
@@ -2401,7 +2406,7 @@
return false;
}
}
-
+
public function getAllErrors(){
$validation = $this->getValidationErrors();
$manual = $this->getManualErrors();
@@ -2451,20 +2456,26 @@
}
/**
- * Runs all the pre-process hooks that have been enabled and configured
in
+ * Runs all the pre-process hooks that have been enabled and configured
in
* donationdata.php and/or LocalSettings.php
- * This function is most likely to be called through
- * executeFunctionIfExists, early on in do_transaction.
+ * This function is most likely to be called through
+ * executeFunctionIfExists, early on in do_transaction.
*/
function runAntifraudHooks() {
+ //extra layer of Stop Doing This.
+ $errors = $this->getTransactionErrors();
+ if ( !empty( $errors ) ) {
+ $this->log( 'Skipping antifraud hooks: Transaction is
already in error' );
+ return;
+ }
// allow any external validators to have their way with the data
$this->log( 'Preparing to run custom filters' );
WmfFramework::runHooks( 'GatewayValidate', array( &$this ) );
$this->log( 'Finished running custom filters' );
- //DO NOT set some variable as getValidationAction() here, and
keep
- //checking that. getValidationAction could change with each one
of these
- //hooks, and this ought to cascade.
+ //DO NOT set some variable as getValidationAction() here, and
keep
+ //checking that. getValidationAction could change with each one
of these
+ //hooks, and this ought to cascade.
// if the transaction was flagged for review
if ( $this->getValidationAction() == 'review' ) {
// expose a hook for external handling of trxns flagged
for review
@@ -2485,11 +2496,11 @@
}
/**
- * Runs all the post-process hooks that have been enabled and
configured in
- * donationdata.php and/or LocalSettings.php, including the
ActiveMQ/Stomp
- * hooks.
- * This function is most likely to be called through
- * executeFunctionIfExists, later on in do_transaction.
+ * Runs all the post-process hooks that have been enabled and
configured in
+ * donationdata.php and/or LocalSettings.php, including the
ActiveMQ/Stomp
+ * hooks.
+ * This function is most likely to be called through
+ * executeFunctionIfExists, later on in do_transaction.
*/
protected function runPostProcessHooks() {
// expose a hook for any post processing
@@ -2498,18 +2509,18 @@
}
/**
- * If there are things about a transaction that we need to stash in the
- * transaction's definition (defined in a local defineTransactions() ),
we
- * can recall them here. Currently, this is only being used to
determine if
- * we have a transaction whose transmission would require multiple
attempts
- * to wait for a certain status (or set of statuses), but we could do
more
- * with this mechanism if we need to.
- * @param string $option_value the name of the key we're looking for in
the
- * transaction definition.
+ * If there are things about a transaction that we need to stash in the
+ * transaction's definition (defined in a local defineTransactions() ),
we
+ * can recall them here. Currently, this is only being used to
determine if
+ * we have a transaction whose transmission would require multiple
attempts
+ * to wait for a certain status (or set of statuses), but we could do
more
+ * with this mechanism if we need to.
+ * @param string $option_value the name of the key we're looking for in
the
+ * transaction definition.
* @return mixed the transaction's value for that key if it exists, or
NULL.
*/
protected function transaction_option( $option_value ) {
- //ooo, ugly.
+ //ooo, ugly.
$transaction = $this->getCurrentTransaction();
if ( !$transaction ){
return NULL;
@@ -2521,18 +2532,18 @@
}
/**
- * Instead of pulling all the DonationData back through to update one
local
- * value, use this. It updates both staged_data (which is intended to
be
- * staged and used _just_ by the gateway) and unstaged_data, which is
actually
- * just normalized and sanitized form data as entered by the user.
- *
- * TODO: handle the cases where $val is listed in the gateway adapter's
- * staged_vars.
- * Not doing this right now, though, because it's not yet necessary for
- * anything we have at the moment.
- *
- * @param string $val The field name that we are looking to retrieve
from
- * our DonationData object.
+ * Instead of pulling all the DonationData back through to update one
local
+ * value, use this. It updates both staged_data (which is intended to be
+ * staged and used _just_ by the gateway) and unstaged_data, which is
actually
+ * just normalized and sanitized form data as entered by the user.
+ *
+ * TODO: handle the cases where $val is listed in the gateway adapter's
+ * staged_vars.
+ * Not doing this right now, though, because it's not yet necessary for
+ * anything we have at the moment.
+ *
+ * @param string $val The field name that we are looking to retrieve
from
+ * our DonationData object.
*/
function refreshGatewayValueFromSource( $val ) {
$refreshed = $this->dataObj->getVal_Escaped( $val );
@@ -2553,17 +2564,17 @@
}
/**
- * Sets the current validation action. This is meant to be used by the
- * process hooks, and as such, by default, only worse news than was
already
- * being stored will be retained for the final result.
- * @param string $action the value you want to set as the action.
- * @param bool $reset set to true to do a hard set on the action value.
- * Otherwise, the status will only change if it fails harder than it
already
+ * Sets the current validation action. This is meant to be used by the
+ * process hooks, and as such, by default, only worse news than was
already
+ * being stored will be retained for the final result.
+ * @param string $action the value you want to set as the action.
+ * @param bool $reset set to true to do a hard set on the action value.
+ * Otherwise, the status will only change if it fails harder than it
already
* was.
* @throws MWException
*/
public function setValidationAction( $action, $reset = false ) {
- //our choices are:
+ //our choices are:
$actions = array(
'process' => 0,
'review' => 1,
@@ -2585,9 +2596,9 @@
}
/**
- * Returns the current validation action.
- * This will typically get set and altered by the various enabled
process hooks.
- * @return string the current process action.
+ * Returns the current validation action.
+ * This will typically get set and altered by the various enabled
process hooks.
+ * @return string the current process action.
*/
public function getValidationAction() {
if ( !isset( $this->action ) ) {
@@ -2595,11 +2606,11 @@
}
return $this->action;
}
-
+
/**
* Lets the outside world (particularly hooks that accumulate points
scores)
- * know if we are a batch processor.
- * @return type
+ * know if we are a batch processor.
+ * @return type
*/
public function isBatchProcessor(){
if (!property_exists($this, 'batch')){
@@ -2633,8 +2644,8 @@
public function getOriginalValidationErrors( ){
return $this->dataObj->getValidationErrors();
}
-
- //TODO: Maybe validate on $unstaged_data directly?
+
+ //TODO: Maybe validate on $unstaged_data directly?
public function revalidate( $check_not_empty = array() ){
$validation_errors = $this->dataObj->getValidationErrors( true,
$check_not_empty );
$this->setValidationErrors( $validation_errors );
@@ -2734,7 +2745,7 @@
* This custom filter function checks the global variable:
*
* UtmCampaignMap
- *
+ *
* @TODO: All these regex map matching functions that are identical with
* different internal var names are making me rilly mad. Collapse.
*
@@ -2779,9 +2790,9 @@
*
* UtmMediumMap
*
- * @TODO: Again. Regex map matching functions, identical, with minor
+ * @TODO: Again. Regex map matching functions, identical, with minor
* internal var names. Collapse.
- *
+ *
* How the score is tabulated:
* - Add the score(value) associated with each regex(key) in the map
var.
*
@@ -3276,7 +3287,7 @@
* around with this in RapidHTML when we try to load it and fail.
*/
public function setValidForm() {
- //do we even need the visual stuff?
+ //do we even need the visual stuff?
if ( $this->isApiRequest() || $this->isBatchProcessor() ) {
return;
}
diff --git a/worldpay_gateway/worldpay.adapter.php
b/worldpay_gateway/worldpay.adapter.php
index 90124a0..eb30077 100644
--- a/worldpay_gateway/worldpay.adapter.php
+++ b/worldpay_gateway/worldpay.adapter.php
@@ -456,11 +456,14 @@
}
function defineErrorMap() {
+ //Well, this is probably going to get annoying as soon as we
want to get specific here.
+ //We can't just use numbers here: We're going to have to break
it out by request and number.
$this->error_map = array(
// Internal messages
'internal-0000' => 'donate_interface-processing-error',
// Failed failed pre-process checks.
'internal-0001' => 'donate_interface-processing-error',
// Transaction could not be processed due to an internal error.
'internal-0002' => 'donate_interface-processing-error',
// Communication failure
+ 'internal-0003' => 'donate_interface-processing-error',
// Some error code returned from one of the daisy-chained requests.
);
}
@@ -668,6 +671,8 @@
// PaymentTrust codes
// Anything other than 2050 or 2100 must be treated as failure
for PT-A or PT-S or PT-R.
// Anything other than 2170 must be treated as failure for PT-C.
+ // ***LOOK AT THIS COMMENT: If you add AuthorizePaymentForFraud
success statuses here,
+ // you will need to whack a finalizeInternalStatus in
do_transaction_QueryAuthorizeDeposit
$this->addCodeRange( 'AuthorizePaymentForFraud', 'MessageCode',
'failed', 2000, 2049 );
$this->addCodeRange( 'AuthorizePaymentForFraud', 'MessageCode',
'failed', 2051, 2099 );
$this->addCodeRange( 'AuthorizePaymentForFraud', 'MessageCode',
'failed', 2101, 2999 );
@@ -760,11 +765,40 @@
}
/**
- * Will return an empty array; errors can only be detected in
processData()
- * @param DOMDocument $response
+ * Check the response data for error conditions, and return them.
+ *
+ * If the site has $wgDonationInterfaceDisplayDebug = true, then the
real
+ * messages will be sent to the client. Messages will not be translated
or
+ * obfuscated.
+ *
+ * @param DOMDocument $response The XML response data all
loaded into a DOMDocument
+ * @return array
*/
function getResponseErrors( $response ) {
- return array();
+ $code = false;
+ $message = false;
+ $errors = array( );
+
+ //only expecting one code / message. Everything else would be
extreme edgecase time
+ foreach ( $response->getElementsByTagName( 'MessageCode' ) as
$node ) {
+ $code = $node->nodeValue;
+ break;
+ }
+ foreach ( $response->getElementsByTagName( 'Message' ) as $node
) {
+ $message = $node->nodeValue;
+ break;
+ }
+
+ if ( $code ) {
+ //determine if the response code is, in fact, an error.
+ $action = $this->findCodeAction(
$this->getCurrentTransaction(), 'MessageCode', $code );
+ if ( $action === 'failed' ) {
+ //use generic internals, I think.
+ //I can't tell if I'm being lazy here, or if we
genuinely don't need to get specific with this.
+ $errors[$code] = ( $this->getGlobal(
'DisplayDebug' ) ) ? '*** ' . $message : $this->getErrorMapByCodeAndTranslate(
'internal-0003' );
+ }
+ }
+ return $errors;
}
/**
@@ -775,60 +809,63 @@
public function processResponse( $response, &$retryVars = null ) {
$self = $this;
$addData = function( $pull_vars ) use ( $response, $self ) {
- $emptyVars = array();
- $addme = array ( );
- foreach ( $pull_vars as $theirs => $ours ) {
- if ( isset( $response['data'][$theirs] ) ) {
- $addme[$ours] =
$response['data'][$theirs];
- } else {
- $emptyVars[] = $theirs;
+ $emptyVars = array( );
+ $addme = array( );
+ foreach ( $pull_vars as $theirs => $ours ) {
+ if ( isset( $response['data'][$theirs]
) ) {
+ $addme[$ours] =
$response['data'][$theirs];
+ } else {
+ $emptyVars[] = $theirs;
+ }
}
- }
- $self->addData( $addme, 'response' );
- return $emptyVars;
- };
+ $self->addData( $addme, 'response' );
+ return $emptyVars;
+ };
$setFailOnEmpty = function( $emptyVars ) use ( $response, $self
) {
- if ( count( $emptyVars ) !== 0 ) {
- $self->setTransactionResult( false, 'status' );
- $self->setTransactionResult( array(
- 'internal-0001' =>
$self->getErrorMapByCodeAndTranslate( 'internal-0001' ),
- 'errors',
- ));
- $code = isset( $response['data']['MessageCode']
) ? $response['data']['MessageCode'] : 'None given';
- $message = isset( $response['data']['Message']
) ? $response['data']['Message'] : 'None given';
- $self->setTransactionResult(
- "Transaction failed (empty vars):
({$code}) {$message}",
- 'message'
- );
- }
- };
+ if ( count( $emptyVars ) !== 0 ) {
+ $self->setTransactionResult( false,
'status' );
+ $self->setTransactionResult( array(
+ 'internal-0001' =>
$self->getErrorMapByCodeAndTranslate( 'internal-0001' )),
+ 'errors'
+ );
+ $code = isset(
$response['data']['MessageCode'] ) ? $response['data']['MessageCode'] : 'None
given';
+ $message = isset(
$response['data']['Message'] ) ? $response['data']['Message'] : 'None given';
+ $self->setTransactionResult(
+ "Transaction failed (empty
vars): ({$code}) {$message}", 'message'
+ );
+ return $code;
+ }
+ return null;
+ };
+ $return = null;
switch ( $this->getCurrentTransaction() ) {
case 'GenerateToken':
- $setFailOnEmpty( $addData( array(
+ $return = $setFailOnEmpty( $addData( array(
'OTT' => 'wp_one_time_token',
'OTTProcessURL' => 'wp_process_url',
'RDID' => 'wp_rdid',
- )));
+ ) ) );
break;
case 'QueryTokenData':
- $setFailOnEmpty( $addData( array(
+ $return = $setFailOnEmpty( $addData( array(
'CardId' => 'wp_card_id',
'CreditCardType' => 'payment_submethod',
- )));
+ ) ) );
break;
case 'AuthorizePaymentForFraud':
- $setFailOnEmpty( $addData( array(
+ $return = $setFailOnEmpty( $addData( array(
'CVNMatch' => 'cvv_result',
'AddressMatch' => 'avs_address',
'PostalCodeMatch' => 'avs_zip',
'PTTID' => 'wp_pttid'
- )));
+ ) ) );
$this->dataObj->expunge( 'cvv' );
break;
}
+ return $return;
}
function getResponseData( $response ) {
@@ -1064,6 +1101,10 @@
$this->log(
"Finalizing transaction at
AuthorizePaymentForFraud to {$result_status}. Code: {$code}"
);
+ //NOOOOO.
+ //Except: Sure. For now. The only reason this
works here, though,
+ //is that all the success statuses for
intermediate transactions
+ //are not defined in defineReturnValueMap().
$this->finalizeInternalStatus( $result_status );
return $result;
}
--
To view, visit https://gerrit.wikimedia.org/r/165902
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib20694516851a8cebc23a29887d32839a46ed430
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/DonationInterface
Gerrit-Branch: deploy-payments_1.22
Gerrit-Owner: Katie Horn <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits