jenkins-bot has submitted this change and it was merged.
Change subject: Be less magical about unstaging order status things
......................................................................
Be less magical about unstaging order status things
Following the paypal_express model, whitelist fields we expect to get back from
each API call, and add those to our normalized response data.
Bug: T141487
Change-Id: I8e6d044f17cd3d875a3da93adf6303abbcd3c3b5
---
M gateway_common/gateway.adapter.php
M globalcollect_gateway/config/var_map.yaml
M globalcollect_gateway/globalcollect.adapter.php
M tests/phpunit/Adapter/GlobalCollect/GlobalCollectOrphanAdapterTest.php
M tests/phpunit/Adapter/GlobalCollect/GlobalCollectOrphanRectifierTest.php
M tests/phpunit/Adapter/GlobalCollect/GlobalCollectTest.php
M
tests/phpunit/includes/Responses/globalcollect/DO_FINISHPAYMENT_200.testresponse
A
tests/phpunit/includes/Responses/globalcollect/GET_ORDERSTATUS_600_badCvv.testresponse
M tests/phpunit/includes/Responses/globalcollect/SET_PAYMENT_200.testresponse
9 files changed, 124 insertions(+), 134 deletions(-)
Approvals:
Ejegg: Looks good to me, approved
jenkins-bot: Verified
diff --git a/gateway_common/gateway.adapter.php
b/gateway_common/gateway.adapter.php
index 4273bc2..227962f 100644
--- a/gateway_common/gateway.adapter.php
+++ b/gateway_common/gateway.adapter.php
@@ -2603,6 +2603,7 @@
$msg = self::getGatewayName() . ': Email Domain map: '
. print_r( $emailDomainMap, true );
+ // TODO: Remove this weaksalsa debug message...
$this->logger->debug( $msg );
// Lookup a score if it is defined
diff --git a/globalcollect_gateway/config/var_map.yaml
b/globalcollect_gateway/config/var_map.yaml
index 87362a6..37b0b8f 100644
--- a/globalcollect_gateway/config/var_map.yaml
+++ b/globalcollect_gateway/config/var_map.yaml
@@ -9,6 +9,7 @@
ATTEMPTID: attempt_id
AUTHORISATIONID: authorization_id
AMOUNT: amount
+AVSRESULT: avs_result
BANKACCOUNTNUMBER: bank_account_number
BANKAGENZIA: bank_agenzia # dd:IT
BANKCHECKDIGIT: bank_check_digit
@@ -27,6 +28,7 @@
CREDITCARDNUMBER: card_num
CURRENCYCODE: currency_code
CVV: cvv
+CVVRESULT: cvv_result
DATECOLLECT: date_collect
DESCRIPTOR: descriptor # eWallets
DIRECTDEBITTEXT: direct_debit_text
diff --git a/globalcollect_gateway/globalcollect.adapter.php
b/globalcollect_gateway/globalcollect.adapter.php
index 6bc534b..d7be717 100644
--- a/globalcollect_gateway/globalcollect.adapter.php
+++ b/globalcollect_gateway/globalcollect.adapter.php
@@ -367,6 +367,14 @@
'ACTION' => 'GET_ORDERSTATUS',
'VERSION' => '2.0'
),
+ 'response' => array(
+ 'EFFORTID',
+ 'ATTEMPTID',
+ 'CURRENCYCODE',
+ 'AMOUNT',
+ 'AVSRESULT',
+ 'CVVRESULT',
+ ),
);
$this->transactions['CANCEL_PAYMENT'] = array(
@@ -616,43 +624,17 @@
* @return PaymentTransactionResponse
*/
private function transactionConfirm_CreditCard(){
- // Pulling vars straight from the querystring
- $pull_vars = array(
- 'CVVRESULT' => 'cvv_result',
- 'AVSRESULT' => 'avs_result',
- );
- $qsResults = array();
- if ( !$this->isBatchProcessor() ) {
- // FIXME: Refactor as normal unstaging.
- foreach ( $pull_vars as $theirkey => $ourkey) {
- $tmp = WmfFramework::getRequestValue(
$theirkey, null );
- if ( !is_null( $tmp ) ) {
- $qsResults[$ourkey] = $tmp;
- }
- }
- }
+ $is_orphan = $this->isBatchProcessor();
+ if ( !$is_orphan ) {
+ // This was a normal front-end donation.
- $is_orphan = false;
- if ( count( $qsResults ) ){
- // Nothing unusual here. Oh, except we are reading
query parameters from
- // what we hope is a redirect back from the processor,
caused by an earlier
- // transaction.
- $this->addResponseData( $qsResults );
- $logmsg = 'CVV Result from querystring: ' .
$this->getData_Unstaged_Escaped( 'cvv_result' );
- $logmsg .= ', AVS Result from querystring: ' .
$this->getData_Unstaged_Escaped( 'avs_result' );
- $this->logger->info( $logmsg );
-
- // If we have a querystring, this means we're
processing a live donor
- // coming back from GlobalCollect, and the transaction
is not orphaned
// @deprecated We should be able to skip any deletion.
$this->logger->info( 'Donor returned, deleting limbo
message' );
$this->deleteLimboMessage( self::GC_CC_LIMBO_QUEUE );
} else {
- // We're in orphan processing mode, so instead of
waiting around for
- // the user to add more data and complete pending
transactions,
- // interpret this pending code range as "failed".
-
- $is_orphan = true;
+ // We're in orphan processing mode, so a "pending
waiting for donor
+ // input" status means that we'll never complete. Set
this range
+ // to map to "failed".
$this->addCodeRange( 'GET_ORDERSTATUS', 'STATUSID',
FinalStatus::FAILED, 0, 70 );
}
@@ -667,52 +649,17 @@
$status_response = null;
for ( $loops = 0; $loops < $loopcount && !$cancelflag &&
!$problemflag; ++$loops ){
- $gotCVV = false;
$status_result = $this->do_transaction(
'GET_ORDERSTATUS' );
$validationAction = $this->getValidationAction();
- // FIXME: Refactor as normal unstaging.
- $xmlResults = array(
- 'cvv_result' => '',
- 'avs_result' => ''
- );
- $status_response = $status_result->getData();
- if ( !empty( $status_response ) ) {
- foreach ( $pull_vars as $theirkey => $ourkey) {
- if ( !array_key_exists( $theirkey,
$status_response ) ) {
- continue;
- }
- $gotCVV = true;
- $xmlResults[$ourkey] =
$status_response[$theirkey];
- if ( array_key_exists( $ourkey,
$qsResults ) && $qsResults[$ourkey] != $xmlResults[$ourkey] ) {
- $problemflag = true;
- $problemmessage = "$theirkey
value '$qsResults[$ourkey]' from querystring does not match value
'$xmlResults[$ourkey]' from GET_ORDERSTATUS XML";
- }
- }
- // Make sure we're recording the right amounts,
in case donor has
- // opened another window and messed with their
session values
- // since our original INSERT_ORDERWITHPAYMENT.
The donor is
- // being charged the amount they intend to
give, so this isn't
- // a reason to fail the transaction.
- // Since we're adding these via
addResponseData, amount will be
- // divided by 100 in unstaging.
- // FIXME: need a general solution - anything
with a resultswitcher
- // is vulnerable to this kind of thing.
- $xmlResults['amount'] =
$status_response['AMOUNT'];
- $xmlResults['currency_code'] =
$status_response['CURRENCYCODE'];
- }
- $this->addResponseData( $xmlResults );
- $logmsg = 'CVV Result from XML: ' .
$this->getData_Unstaged_Escaped( 'cvv_result' );
- $logmsg .= ', AVS Result from XML: ' .
$this->getData_Unstaged_Escaped( 'avs_result' );
+ $gotCVV = !empty( $this->getData_Unstaged_Escaped(
'cvv_result' ) );
+ // TODO: This logging is redundant with the response
from GET_ORDERSTATUS.
+ $logmsg = 'CVV Result: ' .
$this->getData_Unstaged_Escaped( 'cvv_result' );
+ $logmsg .= ', AVS Result: ' .
$this->getData_Unstaged_Escaped( 'avs_result' );
$this->logger->info( $logmsg );
// FIXME: "isForceCancel"?
if ( $status_result->getForceCancel() ) {
$cancelflag = true; //don't retry or MasterCard
will fine us
- }
-
- if ( $is_orphan && !$cancelflag && !empty(
$status_response ) ) {
- $action = $this->findCodeAction(
'GET_ORDERSTATUS', 'STATUSID', $status_response['STATUSID'] );
- $validationAction =
$this->getValidationAction();
}
//we filtered
@@ -790,8 +737,10 @@
// FIXME: explicit that we want
to fall through?
case FinalStatus::PENDING :
- //if it's really pending at
this point, we need to...
- //...leave it alone. If we're
orphan slaying, this will stay in the queue.
+ // If it's really pending at
this point, we need to
+ // leave it alone.
+ // FIXME: If we're orphan
slaying, this should stay in
+ // the queue, but we currently
delete it.
break 2;
}
}
@@ -800,23 +749,6 @@
//if we got here with no problemflag,
//confirm or cancel the payment based on $cancelflag
if ( !$problemflag ){
- if ( is_array( $status_response ) ) {
- // FIXME: Refactor as normal unstaging.
- //if they're set, get CVVRESULT && AVSRESULT
- $pull_vars['EFFORTID'] = 'effort_id';
- $pull_vars['ATTEMPTID'] = 'attempt_id';
- $addme = array();
- foreach ( $pull_vars as $theirkey => $ourkey) {
- if ( array_key_exists( $theirkey,
$status_response ) ){
- $addme[$ourkey] =
$status_response[$theirkey];
- }
- }
-
- if ( count( $addme ) ){
- $this->addResponseData( $addme );
- }
- }
-
if ( !$cancelflag ) {
$final = $this->do_transaction( 'SET_PAYMENT' );
if ( $final->getCommunicationStatus() === true
) {
@@ -1478,6 +1410,15 @@
$retryVars
);
}
+
+ // Unstage any data that we've whitelisted.
+ // TODO: This should be generalized into the base class.
+ $whitelisted_keys = $this->transaction_option( 'response' );
+ if ( $whitelisted_keys ) {
+ $filtered_data = array_intersect_key( $data,
array_flip( $whitelisted_keys ) );
+ $unstaged = $this->unstageKeys( $filtered_data );
+ $this->addResponseData( $unstaged );
+ }
}
public function stageData() {
diff --git
a/tests/phpunit/Adapter/GlobalCollect/GlobalCollectOrphanAdapterTest.php
b/tests/phpunit/Adapter/GlobalCollect/GlobalCollectOrphanAdapterTest.php
index dc40bef..3de7a8d 100644
--- a/tests/phpunit/Adapter/GlobalCollect/GlobalCollectOrphanAdapterTest.php
+++ b/tests/phpunit/Adapter/GlobalCollect/GlobalCollectOrphanAdapterTest.php
@@ -170,24 +170,36 @@
}
/**
- * Don't fraud-fail someone for bad CVV if GET_ORDERSTATUS
- * comes back with STATUSID 25 and no CVVRESULT
- * @group CvvResult
+ * Make sure we're incorporating GET_ORDERSTATUS AVS and CVV responses
into
+ * fraud scores.
*/
- function testConfirmCreditCardStatus25() {
+ function testGetOrderstatusPostProcessFraud() {
+ $this->setMwGlobals( array(
+ 'wgDonationInterfaceEnableCustomFilters' => true,
+ 'wgGlobalCollectGatewayCustomFiltersFunctions' => array(
+ 'getCVVResult' => 10,
+ 'getAVSResult' => 30,
+ ),
+ ) );
$gateway = $this->getFreshGatewayObject( null, array (
'order_id_meta' => array ( 'generate' => FALSE ) ) );
$init = array_merge( $this->getDonorTestData(),
$this->dummy_utm_data );
$init['ffname'] = 'cc-vmad';
$init['order_id'] = '55555';
- $init['email'] = '[email protected]';
+ $init['email'] = '[email protected]';
$init['contribution_tracking_id'] = mt_rand();
+ $init['payment_method'] = 'cc';
$gateway->loadDataAndReInit( $init, $useDB = false );
- $gateway->setDummyGatewayResponseCode( '25' );
+ $gateway->setDummyGatewayResponseCode( '600_badCvv' );
$gateway->do_transaction( 'Confirm_CreditCard' );
$action = $gateway->getValidationAction();
- $this->assertEquals( 'process', $action, 'Gateway should not
fraud fail on STATUSID 25' );
+ $this->assertEquals( 'review', $action,
+ 'Orphan gateway should fraud fail on bad CVV and AVS' );
+
+ $exposed = TestingAccessWrapper::newFromObject( $gateway );
+ $this->assertEquals( 40, $exposed->risk_score,
+ 'Risk score was incremented correctly.' );
}
}
diff --git
a/tests/phpunit/Adapter/GlobalCollect/GlobalCollectOrphanRectifierTest.php
b/tests/phpunit/Adapter/GlobalCollect/GlobalCollectOrphanRectifierTest.php
index dd3c0f6..51095bb 100644
--- a/tests/phpunit/Adapter/GlobalCollect/GlobalCollectOrphanRectifierTest.php
+++ b/tests/phpunit/Adapter/GlobalCollect/GlobalCollectOrphanRectifierTest.php
@@ -77,9 +77,7 @@
$this->pendingDb = PendingDatabase::get();
// Create the schema.
- // FIXME: Reuse something from SmashPig\Tests
- $sql = file_get_contents( __DIR__ .
'/../../../../vendor/wikimedia/smash-pig/Schema/sqlite/001_CreatePendingTable.sql'
);
- $this->pendingDb->getDatabase()->exec( $sql );
+ $this->pendingDb->createTable();
}
/**
diff --git a/tests/phpunit/Adapter/GlobalCollect/GlobalCollectTest.php
b/tests/phpunit/Adapter/GlobalCollect/GlobalCollectTest.php
index c11b2c6..70c1ce9 100644
--- a/tests/phpunit/Adapter/GlobalCollect/GlobalCollectTest.php
+++ b/tests/phpunit/Adapter/GlobalCollect/GlobalCollectTest.php
@@ -194,26 +194,36 @@
}
/**
- * If CVVRESULT is unrecognized, fraud-fail and warn
- * @group CvvResult
+ * Make sure we're incorporating GET_ORDERSTATUS AVS and CVV responses
into
+ * fraud scores.
*/
- function testConfirmCreditCardBadCVVResult() {
+ function testGetOrderstatusPostProcessFraud() {
+ $this->setMwGlobals( array(
+ 'wgDonationInterfaceEnableCustomFilters' => true,
+ 'wgGlobalCollectGatewayCustomFiltersFunctions' => array(
+ 'getCVVResult' => 10,
+ 'getAVSResult' => 30,
+ ),
+ ) );
+
$init = $this->getDonorTestData();
+ $init['ffname'] = 'cc-vmad';
+ $init['order_id'] = '55555';
+ $init['email'] = '[email protected]';
+ $init['contribution_tracking_id'] = mt_rand();
$init['payment_method'] = 'cc';
- $init['payment_submethod'] = 'visa';
- $init['email'] = '[email protected]';
-
- $this->setUpRequest( array( 'CVVRESULT' => ' ' ) );
- DonationInterface_FraudFiltersTest::setupFraudMaps( $this );
-
$gateway = $this->getFreshGatewayObject( $init );
- $gateway->setDummyGatewayResponseCode( '800' );
+
+ $gateway->setDummyGatewayResponseCode( '600_badCvv' );
$gateway->do_transaction( 'Confirm_CreditCard' );
- $result = $gateway->getCvvResult();
- $this->assertEquals( false, $result, 'Gateway should fraud fail
if CVVRESULT is not mapped' );
- $matches = $this->getLogMatches( LogLevel::WARNING,
"/Unrecognized cvv_result ' '$/" );
- $this->assertNotEmpty( $matches, 'Did not log expected warning
on unmapped CVVRESULT' );
+ $action = $gateway->getValidationAction();
+ $this->assertEquals( 'review', $action,
+ 'Orphan gateway should fraud fail on bad CVV and AVS' );
+
+ $exposed = TestingAccessWrapper::newFromObject( $gateway );
+ $this->assertEquals( 40, $exposed->risk_score,
+ 'Risk score was incremented correctly.' );
}
/**
@@ -233,24 +243,6 @@
$gateway->do_transaction( 'Confirm_CreditCard' );
$this->assertEquals( 'N',
$gateway->getData_Unstaged_Escaped('cvv_result'), 'CVV Result not taken from
XML response' );
- }
-
- /**
- * If querystring and XML have different CVVRESULT, that's awfully fishy
- */
- function testConfirmCreditCardFailsOnCvvResultConflict() {
- $init = $this->getDonorTestData();
- $init['payment_method'] = 'cc';
- $init['payment_submethod'] = 'visa';
- $init['email'] = '[email protected]';
-
- $this->setUpRequest( array( 'CVVRESULT' => 'M' ) );
-
- $gateway = $this->getFreshGatewayObject( $init );
-
- $result = $gateway->do_transaction( 'Confirm_CreditCard' );
- // FIXME: this is not a communication failure, it's a fraud
failure
- $this->assertFalse( $result->getCommunicationStatus(), 'Credit
card should fail if querystring and XML have different CVVRESULT' );
}
/**
@@ -350,6 +342,8 @@
'SWIFTCODE' => 'swift_code',
'TRANSACTIONTYPE' => 'transaction_type',
'FISCALNUMBER' => 'fiscal_number',
+ 'AVSRESULT' => 'avs_result',
+ 'CVVRESULT' => 'cvv_result',
);
$exposed = TestingAccessWrapper::newFromObject( $gateway );
diff --git
a/tests/phpunit/includes/Responses/globalcollect/DO_FINISHPAYMENT_200.testresponse
b/tests/phpunit/includes/Responses/globalcollect/DO_FINISHPAYMENT_200.testresponse
index 6efeaf0..4da431e 100644
---
a/tests/phpunit/includes/Responses/globalcollect/DO_FINISHPAYMENT_200.testresponse
+++
b/tests/phpunit/includes/Responses/globalcollect/DO_FINISHPAYMENT_200.testresponse
@@ -22,7 +22,7 @@
<RESPONSEDATETIME>20140327165513</RESPONSEDATETIME>
</META>
<ROW>
- <AMOUNT>10101</AMOUNT>
+ <AMOUNT>2345</AMOUNT>
<CURRENCYCODE>EUR</CURRENCYCODE>
<STATUSID>800</STATUSID>
<STATUSDATE>20140704021814</STATUSDATE>
diff --git
a/tests/phpunit/includes/Responses/globalcollect/GET_ORDERSTATUS_600_badCvv.testresponse
b/tests/phpunit/includes/Responses/globalcollect/GET_ORDERSTATUS_600_badCvv.testresponse
new file mode 100644
index 0000000..7bc87f6
--- /dev/null
+++
b/tests/phpunit/includes/Responses/globalcollect/GET_ORDERSTATUS_600_badCvv.testresponse
@@ -0,0 +1,42 @@
+<XML>
+ <REQUEST>
+ <ACTION>GET_ORDERSTATUS</ACTION>
+ <META>
+ <MERCHANTID>1</MERCHANTID>
+ <IPADDRESS>123.123.123.123</IPADDRESS>
+ <VERSION>2.0</VERSION>
+ <REQUESTIPADDRESS>123.123.123.123</REQUESTIPADDRESS>
+ </META>
+ <PARAMS>
+ <ORDER>
+ <ORDERID>9998890004</ORDERID>
+ </ORDER>
+ </PARAMS>
+ <RESPONSE>
+ <RESULT>OK</RESULT>
+ <META>
+ <REQUESTID>245</REQUESTID>
+
<RESPONSEDATETIME>20100419133351</RESPONSEDATETIME>
+ </META>
+ <STATUS>
+ <PAYMENTMETHODID>1</PAYMENTMETHODID>
+ <STATUSID>600</STATUSID>
+ <CURRENCYCODE>EUR</CURRENCYCODE>
+ <FRAUDRESULT>N</FRAUDRESULT>
+ <EFFORTID>1</EFFORTID>
+
<CREDITCARDNUMBER>************7977</CREDITCARDNUMBER>
+ <AUTHORISATIONCODE>654321</AUTHORISATIONCODE>
+
<PAYMENTREFERENCE>900100000010</PAYMENTREFERENCE>
+ <ATTEMPTID>2</ATTEMPTID>
+ <MERCHANTID>1</MERCHANTID>
+ <AMOUNT>2345</AMOUNT>
+ <STATUSDATE>20100419132926</STATUSDATE>
+ <PAYMENTPRODUCTID>1</PAYMENTPRODUCTID>
+ <CVVRESULT>N</CVVRESULT>
+ <AVSRESULT>E</AVSRESULT>
+ <ORDERID>9998890004</ORDERID>
+ <EXPIRYDATE>1210</EXPIRYDATE>
+ </STATUS>
+ </RESPONSE>
+ </REQUEST>
+</XML>
diff --git
a/tests/phpunit/includes/Responses/globalcollect/SET_PAYMENT_200.testresponse
b/tests/phpunit/includes/Responses/globalcollect/SET_PAYMENT_200.testresponse
index a88c1d1..b721820 100644
---
a/tests/phpunit/includes/Responses/globalcollect/SET_PAYMENT_200.testresponse
+++
b/tests/phpunit/includes/Responses/globalcollect/SET_PAYMENT_200.testresponse
@@ -12,7 +12,7 @@
<ORDERID>626113410</ORDERID>
<EFFORTID>1</EFFORTID>
<PAYMENTPRODUCTID>1</PAYMENTPRODUCTID>
- <AMOUNT>10101</AMOUNT>
+ <AMOUNT>2345</AMOUNT>
<CURRENCYCODE>EUR</CURRENCYCODE>
<MERCHANTREFERENCE>626113410</MERCHANTREFERENCE>
</PAYMENT>
--
To view, visit https://gerrit.wikimedia.org/r/306852
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I8e6d044f17cd3d875a3da93adf6303abbcd3c3b5
Gerrit-PatchSet: 18
Gerrit-Project: mediawiki/extensions/DonationInterface
Gerrit-Branch: master
Gerrit-Owner: Awight <[email protected]>
Gerrit-Reviewer: AndyRussG <[email protected]>
Gerrit-Reviewer: Awight <[email protected]>
Gerrit-Reviewer: Cdentinger <[email protected]>
Gerrit-Reviewer: Ejegg <[email protected]>
Gerrit-Reviewer: Ssmith <[email protected]>
Gerrit-Reviewer: XenoRyet <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits