/**
  * @param string $filterListGlobal Run filters listed in a DonationInterface
  *                                 global variable with name
  * @return bool
  */
 protected function filter($filterListGlobal)
 {
     $functions = $this->gateway_adapter->getGlobal($filterListGlobal);
     if (!$this->gateway_adapter->getGlobal('EnableFunctionsFilter') || !count($functions)) {
         return true;
     }
     foreach ($functions as $function_name => $risk_score_modifier) {
         //run the function specified, if it exists.
         if (method_exists($this->gateway_adapter, $function_name)) {
             $score = $this->gateway_adapter->{$function_name}();
             if (is_null($score)) {
                 $score = 0;
                 //TODO: Is this the correct behavior?
             } elseif (is_bool($score)) {
                 $score = $score ? 0 : $risk_score_modifier;
             } elseif (is_numeric($score) && $score <= 100) {
                 $score = $score * $risk_score_modifier / 100;
             } else {
                 //					error_log("Function Filter: $function_name returned $score");
                 throw new UnexpectedValueException("Filter functions are returning somekinda nonsense.");
             }
             $this->cfo->addRiskScore($score, $function_name);
         }
     }
     return TRUE;
 }
 static function singleton(&$gateway_adapter)
 {
     if (!self::$instance || $gateway_adapter->isBatchProcessor()) {
         self::$instance = new self($gateway_adapter);
     }
     return self::$instance;
 }
 protected function filter()
 {
     // pull out the source from the filter object
     $source = $this->gateway_adapter->getData_Unstaged_Escaped('utm_source');
     // a very complex filtering algorithm for sources
     $srcRules = $this->gateway_adapter->getGlobal('CustomFiltersSrcRules');
     foreach ($srcRules as $regex => $risk_score_modifier) {
         /**
          * Note that regex pattern does not include delimiters.
          * These will need to be included in your custom regex patterns.
          */
         if (preg_match("{$regex}", $source)) {
             $this->cfo->addRiskScore($risk_score_modifier, 'source');
             // log it
             $log_msg = "\"" . addslashes($source) . "\"";
             $log_msg .= "\t\"" . addslashes($regex) . "\"";
             $log_msg .= "\t\"" . $this->cfo->getRiskScore() . "\"";
             $this->log($this->gateway_adapter->getData_Unstaged_Escaped('contribution_tracking_id'), 'Filter: Source', $log_msg);
         }
     }
     return TRUE;
 }
 protected function filter()
 {
     // pull out the referrer from the gateway_adapter
     $referrer = $this->gateway_adapter->getData_Unstaged_Escaped('referrer');
     // a very complex filtering algorithm for referrers
     $refRules = $this->gateway_adapter->getGlobal('CustomFiltersRefRules');
     foreach ($refRules as $regex => $risk_score_modifier) {
         /**
          * note that the regex pattern does NOT include delimiters.
          * these will need to be included in your custom regex patterns.
          */
         if (preg_match("{$regex}", $referrer)) {
             $this->cfo->addRiskScore($risk_score_modifier, 'referrer');
             // log it
             //TODO: This sucks.
             $log_msg = "\"" . addslashes($referrer) . "\"";
             $log_msg .= "\t\"" . addslashes($regex) . "\"";
             $log_msg .= "\t\"" . $this->cfo->getRiskScore() . "\"";
             $this->log($this->gateway_adapter->getData_Unstaged_Escaped('contribution_tracking_id'), 'Filter: Referrer', $log_msg);
         }
     }
     return TRUE;
 }
 /**
  * Execute the minFraud filter
  *
  * @return bool true
  */
 protected function filter()
 {
     // see if we can bypass minfraud
     if ($this->can_bypass_minfraud()) {
         return TRUE;
     }
     $minfraud_query = $this->build_query($this->gateway_adapter->getData_Unstaged_Escaped());
     $this->query_minfraud($minfraud_query);
     // Write the query/response to the log before we go mad.
     $this->log_query();
     $this->health_check();
     try {
         if (!isset($this->minfraudResponse['riskScore'])) {
             throw new RuntimeException("No response at all from minfraud.");
         }
         $this->cfo->addRiskScore($this->minfraudResponse['riskScore'], 'minfraud_filter');
     } catch (Exception $ex) {
         //log out the whole response to the error log so we can tell what the heck happened... and fail closed.
         $log_message = 'Minfraud filter came back with some garbage. Assigning all the points.';
         $this->fraud_logger->error('"addRiskScore" ' . $log_message);
         $this->cfo->addRiskScore(100, 'minfraud_filter');
     }
     return TRUE;
 }
 /**
  * Add a hit to this IP's history for a toxic card.  This is designed to be
  * called outside of the usual filter callbacks so we record nasty attempts
  * even when the filters aren't called.
  * @param GatewayType $gateway adapter instance with user_ip set
  */
 public static function penalize(GatewayType $gateway)
 {
     $logger = DonationLoggerFactory::getLogger($gateway);
     $logger->info('IPVelocityFilter penalizing IP address ' . $gateway->getData_Unstaged_Escaped('user_ip') . ' for toxic card attempt.');
     $velocity = Gateway_Extras_CustomFilters_IP_Velocity::singleton($gateway, Gateway_Extras_CustomFilters::singleton($gateway));
     if ($velocity->connectToMemcache()) {
         $velocity->addNowToMemcachedValue(null, false, true);
     }
 }
 /**
  * For Adyen, we only call this on the donor's return to the ResultSwitcher
  * @param array $response GET/POST params from request
  * @throws ResponseProcessingException
  */
 public function processResponse($response)
 {
     // Always called outside do_transaction, so just make a new response object
     $this->transaction_response = new PaymentTransactionResponse();
     if (empty($response)) {
         $this->logger->info("No response from gateway");
         throw new ResponseProcessingException('No response from gateway', ResponseCodes::NO_RESPONSE);
     }
     $this->logger->info("Processing user return data: " . print_r($response, TRUE));
     if (!$this->checkResponseSignature($response)) {
         $this->logger->info("Bad signature in response");
         throw new ResponseProcessingException('Bad signature in response', ResponseCodes::BAD_SIGNATURE);
     }
     $this->logger->debug('Good signature');
     // Overwrite the order ID we have with the return data, in case the
     // donor opened a second window.
     $orderId = $response['merchantReference'];
     $this->addRequestData(array('order_id' => $orderId));
     $gateway_txn_id = isset($response['pspReference']) ? $response['pspReference'] : '';
     $this->transaction_response->setGatewayTransactionId($gateway_txn_id);
     $result_code = isset($response['authResult']) ? $response['authResult'] : '';
     if ($result_code == 'PENDING' || $result_code == 'AUTHORISED') {
         // Both of these are listed as pending because we have to submit a capture
         // request on 'AUTHORIZATION' ipn message receipt.
         // We should still have risk scores in the session from before we
         // showed the iframe. What did we decide then? Show a fail page if
         // the donation was fishy enough that our listener isn't going to
         // auto-capture it, so as not to tell carders the auth worked.
         // FIXME: need to keep action ranges in sync between DI and listener.
         $action = Gateway_Extras_CustomFilters::determineStoredAction($this);
         if ($action === 'process') {
             $this->logger->info("User came back as pending or authorised, placing in payments-init queue");
             $this->finalizeInternalStatus(FinalStatus::PENDING);
         } else {
             $this->logger->info("User came back authorized but with action {$action}. " . "Showing a fail page, but leaving details in case of manual capture.");
             $this->finalizeInternalStatus(FinalStatus::FAILED);
         }
     } else {
         $this->finalizeInternalStatus(FinalStatus::FAILED);
         $this->logger->info("Negative response from gateway. Full response: " . print_r($response, TRUE));
     }
     $this->postProcessDonation();
 }
 /**
  * Runs all the fraud filters 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.
  */
 function runAntifraudFilters()
 {
     //extra layer of Stop Doing This.
     $errors = $this->getTransactionErrors();
     if (!empty($errors)) {
         $this->logger->info('Skipping antifraud filters: Transaction is already in error');
         return;
     }
     // allow any external validators to have their way with the data
     $this->logger->info('Preparing to run custom filters');
     Gateway_Extras_CustomFilters::onValidate($this);
     $this->logger->info('Finished running custom filters');
 }