jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/275043 )

Change subject: Optionally send more Minfraud parameters
......................................................................


Optionally send more Minfraud parameters

List the extra fields you want to send in
$wgDonationInterfaceMinFraudExtraFields.

Available: 'email', 'first_name', 'last_name', 'street_address',
'amount', and 'currency'.

Also cleans up some unused CCFD (old minfraud lib) references.

Bug: T128902
Bug: T173876
Change-Id: I3b48de91ac417cf245fd23a5bfcf80c7cb3bbad2
---
M README.txt
M extension.json
M extras/custom_filters/filters/minfraud/minfraud.body.php
M tests/phpunit/FraudFiltersTest.php
A tests/phpunit/includes/Responses/minFraud/15points.json
5 files changed, 154 insertions(+), 59 deletions(-)

Approvals:
  XenoRyet: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/README.txt b/README.txt
index 1a5f1f5..c9f16e1 100644
--- a/README.txt
+++ b/README.txt
@@ -414,6 +414,16 @@
  */
 $wgDonationInterfaceMinFraudAlarmLimit = 25000
 
+/**
+ * Additional fields to send in each Minfraud request.
+ * Parameter documentation: http://dev.maxmind.com/minfraud/#Input
+ * We will always send city, region, postal, country, domain, email (MD5
+ * hashed), transaction_id, ip_address, user_agent, and accept_language.
+ * Things you can put here: email (send the real address instead of a hash),
+ * amount, currency, first_name, last_name, and street_address.
+ */
+$wgDonationInterfaceMinFraudExtraFields = array()
+
 //Referrer Filter globals
 $wgDonationInterfaceCustomFiltersRefRules = array()
 
diff --git a/extension.json b/extension.json
index 2c1041a..760c469 100644
--- a/extension.json
+++ b/extension.json
@@ -475,6 +475,7 @@
                "DonationInterfaceMinFraudUserId": "",
                "DonationInterfaceMinFraudLicenseKey": "",
                "DonationInterfaceMinFraudClientOptions": [],
+               "DonationInterfaceMinFraudExtraFields": [],
                "DonationInterfaceMinFraudAlarmLimit": 25000,
                "DonationInterfaceCustomFiltersRefRules": [],
                "DonationInterfaceCustomFiltersSrcRules": [],
diff --git a/extras/custom_filters/filters/minfraud/minfraud.body.php 
b/extras/custom_filters/filters/minfraud/minfraud.body.php
index fcd5b4d..828986e 100644
--- a/extras/custom_filters/filters/minfraud/minfraud.body.php
+++ b/extras/custom_filters/filters/minfraud/minfraud.body.php
@@ -64,13 +64,13 @@
         * @see MaxMind\MinFraud
         * @var array $minFraudClientOptions
         */
-       protected $minFraudClientOptions = array();
+       protected $minFraudClientOptions = [];
 
        /**
-        * License key for minfraud
-        * @var string $minfraudLicenseKey
+        * License key for minFraud
+        * @var string $minFraudLicenseKey
         */
-       protected $minfraudLicenseKey = '';
+       protected $minFraudLicenseKey = '';
 
        /**
         * Instance of Gateway_Extras_CustomFilters_MinFraud
@@ -83,6 +83,35 @@
         * @var \Psr\Log\LoggerInterface
         */
        protected $fraud_logger;
+
+       /**
+        * Extra fields to send to minFraud. These should be our normalized 
field
+        * names, not the minFraud field names.
+        * When 'email' is specified as an extra, it means we will send the real
+        * address instead of the md5 hash.
+        *
+        * See http://dev.maxmind.com/minfraud/#Input
+        * @var string[] $enabledExtraFields
+        */
+       protected $enabledExtraFields = [];
+
+       /**
+        * Top level keys indicate the grouping under the minFraud scheme.
+        * Second level keys are our field names, values are minFraud field 
names.
+        * @var array $extraFieldsMap
+        */
+       protected static $extraFieldsMap = [
+               'email' => [ 'email' => 'address' ],
+               'billing' => [
+                       'first_name' => 'first_name',
+                       'last_name' => 'last_name',
+                       'street_address' => 'address',
+               ],
+               'order' => [
+                       'amount' => 'amount',
+                       'currency' => 'currency'
+               ]
+       ];
 
        /**
         * Constructor
@@ -117,8 +146,12 @@
 
                // Set the minFraud API options
                $minFraudOptions = $gateway_adapter->getGlobal( 
'MinFraudClientOptions' );
-               if ( !empty( $minFraudOptions ) && is_array( $minFraudOptions ) 
) {
+               if ( is_array( $minFraudOptions ) ) {
                        $this->minFraudClientOptions = $minFraudOptions;
+               }
+               $extraFields = $gateway_adapter->getGlobal( 
'MinFraudExtraFields' );
+               if ( is_array( $extraFields ) ) {
+                       $this->enabledExtraFields = $extraFields;
                }
        }
 
@@ -141,12 +174,14 @@
         * @return array all parameters for the query
         */
        protected function buildQuery( array $data ) {
-               return [
+               $standardQuery = [
                        'device' => $this->getDeviceParams( $data ),
                        'email' => $this->getEmailParams( $data ),
                        'billing' => $this->getBillingParams( $data ),
                        'event' => $this->getEventParams( $data ),
                ];
+               $query = $this->withExtraFields( $data, $standardQuery );
+               return $query;
        }
 
        protected function getDeviceParams( $data ) {
@@ -163,7 +198,6 @@
        }
 
        /**
-        * TODO: option to not MD5 the address
         * @param array $data
         * @return array
         */
@@ -190,6 +224,18 @@
                ];
        }
 
+       protected function withExtraFields( $data, $query ) {
+               foreach ( self::$extraFieldsMap as $section => $fields ) {
+                       foreach ( $fields as $ourName => $theirName ) {
+                               if ( array_search( $ourName, 
$this->enabledExtraFields ) !== false ) {
+                                       if ( !empty( $data[$ourName] ) ) {
+                                               $query[$section][$theirName] = 
$data[$ourName];
+                                       }
+                               }
+                       }
+               }
+               return $query;
+       }
        /**
         * Check to see if we can bypass minFraud check
         *
@@ -283,22 +329,6 @@
        }
 
        /**
-        * Get instance of CreditCardFraudDetection
-        * @return CreditCardFraudDetection
-        */
-       protected function get_ccfd() {
-               if ( !$this->ccfd ) {
-                       $this->ccfd = new CreditCardFraudDetection();
-
-                       // Override the minFraud API servers
-                       if ( !empty( $this->minFraudServers ) && is_array( 
$this->minFraudServers ) ) {
-                               $this->ccfd->server = $this->minFraudServers;
-                       }
-               }
-               return $this->ccfd;
-       }
-
-       /**
         * Logs a minFraud query and its response
         *
         * @param array $query parameters sent to minFraud
@@ -343,7 +373,7 @@
        }
 
        /**
-        * Perform the min fraud query and capture the response
+        * Perform the minFraud query and capture the response
         *
         * @param array $query The array you would pass to minFraud in a query
         * @return Score result from minFraud client score() call
@@ -363,6 +393,9 @@
                )->withEvent(
                        $query['event']
                );
+               if ( !empty( $query['order'] ) ) {
+                       $minFraud = $minFraud->withOrder( $query['order'] );
+               }
                return $minFraud->score();
        }
 
diff --git a/tests/phpunit/FraudFiltersTest.php 
b/tests/phpunit/FraudFiltersTest.php
index 3556f55..6499931 100644
--- a/tests/phpunit/FraudFiltersTest.php
+++ b/tests/phpunit/FraudFiltersTest.php
@@ -107,8 +107,7 @@
        }
 
        /**
-        * When minFraud gets a blank answer, we should assign points according 
to
-        * $wgDonationInterfaceMinFraudErrorScore.
+        * Test we correctly add a real score from minFraud
         */
        function testMinFraudRealScore() {
                $options = $this->getDonorTestData();
@@ -126,24 +125,10 @@
                                '"event":{"transaction_id":"' .
                                $gateway->getData_Unstaged_Escaped( 
'contribution_tracking_id' ) .'"}}'
                        )->willReturn( [
-                       200, 'application/json', '{
-       "id": "5bc5d6c2-b2c8-40af-87f4-6d61af86b6ae",
-       "risk_score": 15.25,
-       "funds_remaining": 250.00,
-       "queries_remaining": 500000,
- 
-       "ip_address": {
-               "risk": 15.25
-       },
- 
-       "disposition": {
-                "action": "accept",
-                "reason": "default"
-       },
-
-       "warnings": []
-        }'
-               ] );
+                               200, 'application/json', file_get_contents(
+                                       __DIR__ . 
'/includes/Responses/minFraud/15points.json'
+                               )
+                       ] );
 
                $gateway->runAntifraudFilters();
 
@@ -177,24 +162,73 @@
                );
                $this->assertEquals( $expected, $message );
        }
-}
-// Stub out Minfraud class for CI tests
-if ( !class_exists( 'CreditCardFraudDetection' ) ) {
-       class CreditCardFraudDetection {
-               public $server;
 
-               public function filter_field( $a, $b ) {
-                       return 'blah';
-               }
+       /**
+        * Make sure we send the right stuff when extra fields are enabled
+        */
+       function testMinFraudExtras() {
+               $options = $this->getDonorTestData();
+               $options['email'] = 'someb...@wikipedia.org';
+               $options['payment_method'] = 'cc';
 
-               public function query() {
-               }
+               $gateway = $this->getFreshGatewayObject( $options );
 
-               public function input( $a ) {
-               }
+               $this->setMwGlobals( [
+                       'wgDonationInterfaceMinFraudExtraFields' => [
+                               'email',
+                               'first_name',
+                               'last_name',
+                               'street_address',
+                               'amount',
+                               'currency'
+                       ]
+               ] );
+               $this->request->expects( $this->once() )
+                       ->method( 'post' )
+                       ->with(
+                               '{"billing":{"city":"San 
Francisco","region":"CA","postal":"94105","country":"US",' .
+                               
'"first_name":"Firstname","last_name":"Surname","address":"123 Fake Street"},' .
+                               '"device":{"ip_address":"127.0.0.1"},' .
+                               
'"email":{"address":"someb...@wikipedia.org","domain":"wikipedia.org"},' .
+                               '"event":{"transaction_id":"' .
+                               $gateway->getData_Unstaged_Escaped( 
'contribution_tracking_id' ) .
+                               '"},"order":{"amount":"1.55","currency":"USD"}}'
+                       )->willReturn( [
+                               200, 'application/json', file_get_contents(
+                                       __DIR__ . 
'/includes/Responses/minFraud/15points.json'
+                               )
+                       ] );
 
-               public function output() {
-                       return array();
-               }
+               $gateway->runAntifraudFilters();
+
+               $this->assertEquals( 'challenge', 
$gateway->getValidationAction(), 'Validation action is not as expected' );
+               $exposed = TestingAccessWrapper::newFromObject( $gateway );
+               $this->assertEquals( 72.75, $exposed->risk_score, 'RiskScore is 
not as expected for failure mode' );
+               $message = QueueWrapper::getQueue( 'payments-antifraud' 
)->pop();
+               SourceFields::removeFromMessage( $message );
+               $expected = array(
+                       'validation_action' => 'challenge',
+                       'risk_score' => 72.75,
+                       'score_breakdown' => array(
+                               'initial' => 0,
+                               'getScoreUtmCampaignMap' => 0,
+                               'getScoreCountryMap' => 20,
+                               'getScoreUtmSourceMap' => 0,
+                               'getScoreUtmMediumMap' => 0,
+                               'getScoreEmailDomainMap' => 37.5,
+                               'getCVVResult' => 0,
+                               'getAVSResult' => 0,
+                               'minfraud_filter' => 15.25,
+                       ),
+                       'user_ip' => '127.0.0.1',
+                       'gateway_txn_id' => false,
+                       'date' => $message['date'],
+                       'server' => gethostname(),
+                       'gateway' => 'globalcollect',
+                       'contribution_tracking_id' => 
$gateway->getData_Unstaged_Escaped( 'contribution_tracking_id' ),
+                       'order_id' => $gateway->getData_Unstaged_Escaped( 
'order_id' ),
+                       'payment_method' => 'cc',
+               );
+               $this->assertEquals( $expected, $message );
        }
 }
diff --git a/tests/phpunit/includes/Responses/minFraud/15points.json 
b/tests/phpunit/includes/Responses/minFraud/15points.json
new file mode 100644
index 0000000..35bc1cb
--- /dev/null
+++ b/tests/phpunit/includes/Responses/minFraud/15points.json
@@ -0,0 +1,17 @@
+{
+  "id": "5bc5d6c2-b2c8-40af-87f4-6d61af86b6ae",
+  "risk_score": 15.25,
+  "funds_remaining": 250.00,
+  "queries_remaining": 500000,
+
+  "ip_address": {
+    "risk": 15.25
+  },
+
+  "disposition": {
+    "action": "accept",
+    "reason": "default"
+  },
+
+  "warnings": []
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/275043
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I3b48de91ac417cf245fd23a5bfcf80c7cb3bbad2
Gerrit-PatchSet: 14
Gerrit-Project: mediawiki/extensions/DonationInterface
Gerrit-Branch: master
Gerrit-Owner: Ejegg <ej...@ejegg.com>
Gerrit-Reviewer: AndyRussG <andrew.green...@gmail.com>
Gerrit-Reviewer: Cdentinger <cdentin...@wikimedia.org>
Gerrit-Reviewer: Ejegg <ej...@ejegg.com>
Gerrit-Reviewer: Mepps <me...@wikimedia.org>
Gerrit-Reviewer: XenoRyet <dkozlow...@wikimedia.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to