Skip to content

Commit aa93ea8

Browse files
authored
Merge pull request #904 from magento-mpi/MAGETWO-63638
[MPI] S86
2 parents b47cb1f + 80ae35e commit aa93ea8

File tree

23 files changed

+1105
-5
lines changed

23 files changed

+1105
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Braintree\Model;
7+
8+
use Magento\Braintree\Model\Ui\ConfigProvider;
9+
use Magento\Braintree\Gateway\Response\PaymentDetailsHandler;
10+
use Magento\Payment\Api\PaymentVerificationInterface;
11+
use Magento\Sales\Api\Data\OrderPaymentInterface;
12+
13+
/**
14+
* Processes AVS codes mapping from Braintree transaction to
15+
* electronic merchant systems standard.
16+
*
17+
* @see https://developers.braintreepayments.com/reference/response/transaction
18+
* @see http://www.emsecommerce.net/avs_cvv2_response_codes.htm
19+
*/
20+
class AvsEmsCodeMapper implements PaymentVerificationInterface
21+
{
22+
/**
23+
* Default code for mismatching mapping.
24+
*
25+
* @var string
26+
*/
27+
private static $unavailableCode = 'U';
28+
29+
/**
30+
* List of mapping AVS codes
31+
*
32+
* @var array
33+
*/
34+
private static $avsMap = [
35+
'MM' => 'Y',
36+
'NM' => 'A',
37+
'MN' => 'Z',
38+
'NN' => 'N',
39+
'UU' => 'U',
40+
'II' => 'U',
41+
'AA' => 'E'
42+
];
43+
44+
/**
45+
* Gets payment AVS verification code.
46+
*
47+
* @param OrderPaymentInterface $orderPayment
48+
* @return string
49+
* @throws \InvalidArgumentException If specified order payment has different payment method code.
50+
*/
51+
public function getCode(OrderPaymentInterface $orderPayment)
52+
{
53+
if ($orderPayment->getMethod() !== ConfigProvider::CODE) {
54+
throw new \InvalidArgumentException(
55+
'The "' . $orderPayment->getMethod() . '" does not supported by Braintree AVS mapper.'
56+
);
57+
}
58+
59+
$additionalInfo = $orderPayment->getAdditionalInformation();
60+
if (empty($additionalInfo[PaymentDetailsHandler::AVS_POSTAL_RESPONSE_CODE]) ||
61+
empty($additionalInfo[PaymentDetailsHandler::AVS_STREET_ADDRESS_RESPONSE_CODE])
62+
) {
63+
return self::$unavailableCode;
64+
}
65+
66+
$streetCode = $additionalInfo[PaymentDetailsHandler::AVS_STREET_ADDRESS_RESPONSE_CODE];
67+
$zipCode = $additionalInfo[PaymentDetailsHandler::AVS_POSTAL_RESPONSE_CODE];
68+
$key = $zipCode . $streetCode;
69+
return isset(self::$avsMap[$key]) ? self::$avsMap[$key] : self::$unavailableCode;
70+
}
71+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Braintree\Model;
7+
8+
use Magento\Braintree\Gateway\Response\PaymentDetailsHandler;
9+
use Magento\Braintree\Model\Ui\ConfigProvider;
10+
use Magento\Payment\Api\PaymentVerificationInterface;
11+
use Magento\Sales\Api\Data\OrderPaymentInterface;
12+
13+
/**
14+
* Processes CVV codes mapping from Braintree transaction to
15+
* electronic merchant systems standard.
16+
*
17+
* @see https://developers.braintreepayments.com/reference/response/transaction
18+
* @see http://www.emsecommerce.net/avs_cvv2_response_codes.htm
19+
*/
20+
class CvvEmsCodeMapper implements PaymentVerificationInterface
21+
{
22+
/**
23+
* Default code for mismatch mapping
24+
*
25+
* @var string
26+
*/
27+
private static $notProvidedCode = 'P';
28+
29+
/**
30+
* List of mapping CVV codes
31+
*
32+
* @var array
33+
*/
34+
private static $cvvMap = [
35+
'M' => 'M',
36+
'N' => 'N',
37+
'U' => 'P',
38+
'I' => 'P',
39+
'S' => 'S',
40+
'A' => ''
41+
];
42+
43+
/**
44+
* Gets payment CVV verification code.
45+
*
46+
* @param OrderPaymentInterface $orderPayment
47+
* @return string
48+
* @throws \InvalidArgumentException If specified order payment has different payment method code.
49+
*/
50+
public function getCode(OrderPaymentInterface $orderPayment)
51+
{
52+
if ($orderPayment->getMethod() !== ConfigProvider::CODE) {
53+
throw new \InvalidArgumentException(
54+
'The "' . $orderPayment->getMethod() . '" does not supported by Braintree CVV mapper.'
55+
);
56+
}
57+
58+
$additionalInfo = $orderPayment->getAdditionalInformation();
59+
if (empty($additionalInfo[PaymentDetailsHandler::CVV_RESPONSE_CODE])) {
60+
return self::$notProvidedCode;
61+
}
62+
63+
$cvv = $additionalInfo[PaymentDetailsHandler::CVV_RESPONSE_CODE];
64+
return isset(self::$cvvMap[$cvv]) ? self::$cvvMap[$cvv] : self::$notProvidedCode;
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Braintree\Test\Unit\Model;
7+
8+
use Magento\Braintree\Model\AvsEmsCodeMapper;
9+
use Magento\Braintree\Model\Ui\ConfigProvider;
10+
use Magento\Sales\Api\Data\OrderPaymentInterface;
11+
use PHPUnit_Framework_MockObject_MockObject as MockObject;
12+
13+
class AvsEmsCodeMapperTest extends \PHPUnit_Framework_TestCase
14+
{
15+
/**
16+
* @var AvsEmsCodeMapper
17+
*/
18+
private $mapper;
19+
20+
/**
21+
* @inheritdoc
22+
*/
23+
protected function setUp()
24+
{
25+
$this->mapper = new AvsEmsCodeMapper();
26+
}
27+
28+
/**
29+
* Checks different variations for AVS codes mapping.
30+
*
31+
* @covers \Magento\Braintree\Model\AvsEmsCodeMapper::getCode
32+
* @param string $avsZip
33+
* @param string $avsStreet
34+
* @param string $expected
35+
* @dataProvider getCodeDataProvider
36+
*/
37+
public function testGetCode($avsZip, $avsStreet, $expected)
38+
{
39+
/** @var OrderPaymentInterface|MockObject $orderPayment */
40+
$orderPayment = $this->getMockBuilder(OrderPaymentInterface::class)
41+
->disableOriginalConstructor()
42+
->getMock();
43+
44+
$orderPayment->expects(self::once())
45+
->method('getMethod')
46+
->willReturn(ConfigProvider::CODE);
47+
48+
$orderPayment->expects(self::once())
49+
->method('getAdditionalInformation')
50+
->willReturn([
51+
'avsPostalCodeResponseCode' => $avsZip,
52+
'avsStreetAddressResponseCode' => $avsStreet
53+
]);
54+
55+
self::assertEquals($expected, $this->mapper->getCode($orderPayment));
56+
}
57+
58+
/**
59+
* Checks a test case, when payment order is not Braintree payment method.
60+
*
61+
* @covers \Magento\Braintree\Model\AvsEmsCodeMapper::getCode
62+
* @expectedException \InvalidArgumentException
63+
* @expectedExceptionMessage The "some_payment" does not supported by Braintree AVS mapper.
64+
*/
65+
public function testGetCodeWithException()
66+
{
67+
/** @var OrderPaymentInterface|MockObject $orderPayment */
68+
$orderPayment = $this->getMockBuilder(OrderPaymentInterface::class)
69+
->disableOriginalConstructor()
70+
->getMock();
71+
72+
$orderPayment->expects(self::exactly(2))
73+
->method('getMethod')
74+
->willReturn('some_payment');
75+
76+
$this->mapper->getCode($orderPayment);
77+
}
78+
79+
/**
80+
* Gets list of AVS codes.
81+
*
82+
* @return array
83+
*/
84+
public function getCodeDataProvider()
85+
{
86+
return [
87+
['avsZip' => null, 'avsStreet' => null, 'expected' => 'U'],
88+
['avsZip' => null, 'avsStreet' => 'M', 'expected' => 'U'],
89+
['avsZip' => 'M', 'avsStreet' => null, 'expected' => 'U'],
90+
['avsZip' => 'M', 'avsStreet' => 'Unknown', 'expected' => 'U'],
91+
['avsZip' => 'I', 'avsStreet' => 'A', 'expected' => 'U'],
92+
['avsZip' => 'M', 'avsStreet' => 'M', 'expected' => 'Y'],
93+
['avsZip' => 'N', 'avsStreet' => 'M', 'expected' => 'A'],
94+
['avsZip' => 'M', 'avsStreet' => 'N', 'expected' => 'Z'],
95+
['avsZip' => 'N', 'avsStreet' => 'N', 'expected' => 'N'],
96+
['avsZip' => 'U', 'avsStreet' => 'U', 'expected' => 'U'],
97+
['avsZip' => 'I', 'avsStreet' => 'I', 'expected' => 'U'],
98+
['avsZip' => 'A', 'avsStreet' => 'A', 'expected' => 'E'],
99+
];
100+
}
101+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Braintree\Test\Unit\Model;
7+
8+
use Magento\Braintree\Model\CvvEmsCodeMapper;
9+
use Magento\Braintree\Model\Ui\ConfigProvider;
10+
use Magento\Sales\Api\Data\OrderPaymentInterface;
11+
use PHPUnit_Framework_MockObject_MockObject as MockObject;
12+
13+
class CvvEmsCodeMapperTest extends \PHPUnit_Framework_TestCase
14+
{
15+
/**
16+
* @var CvvEmsCodeMapper
17+
*/
18+
private $mapper;
19+
20+
/**
21+
* @inheritdoc
22+
*/
23+
protected function setUp()
24+
{
25+
$this->mapper = new CvvEmsCodeMapper();
26+
}
27+
28+
/**
29+
* Checks different variations for cvv codes mapping.
30+
*
31+
* @covers \Magento\Braintree\Model\CvvEmsCodeMapper::getCode
32+
* @param string $cvvCode
33+
* @param string $expected
34+
* @dataProvider getCodeDataProvider
35+
*/
36+
public function testGetCode($cvvCode, $expected)
37+
{
38+
/** @var OrderPaymentInterface|MockObject $orderPayment */
39+
$orderPayment = $this->getMockBuilder(OrderPaymentInterface::class)
40+
->disableOriginalConstructor()
41+
->getMock();
42+
43+
$orderPayment->expects(self::once())
44+
->method('getMethod')
45+
->willReturn(ConfigProvider::CODE);
46+
47+
$orderPayment->expects(self::once())
48+
->method('getAdditionalInformation')
49+
->willReturn(['cvvResponseCode' => $cvvCode]);
50+
51+
self::assertEquals($expected, $this->mapper->getCode($orderPayment));
52+
}
53+
54+
/**
55+
* Checks a test case, when payment order is not Braintree payment method.
56+
*
57+
* @covers \Magento\Braintree\Model\CvvEmsCodeMapper::getCode
58+
* @expectedException \InvalidArgumentException
59+
* @expectedExceptionMessage The "some_payment" does not supported by Braintree CVV mapper.
60+
*/
61+
public function testGetCodeWithException()
62+
{
63+
/** @var OrderPaymentInterface|MockObject $orderPayment */
64+
$orderPayment = $this->getMockBuilder(OrderPaymentInterface::class)
65+
->disableOriginalConstructor()
66+
->getMock();
67+
68+
$orderPayment->expects(self::exactly(2))
69+
->method('getMethod')
70+
->willReturn('some_payment');
71+
72+
$this->mapper->getCode($orderPayment);
73+
}
74+
75+
/**
76+
* Gets variations of cvv codes and expected mapping result.
77+
*
78+
* @return array
79+
*/
80+
public function getCodeDataProvider()
81+
{
82+
return [
83+
['cvvCode' => '', 'expected' => 'P'],
84+
['cvvCode' => null, 'expected' => 'P'],
85+
['cvvCode' => 'Unknown', 'expected' => 'P'],
86+
['cvvCode' => 'M', 'expected' => 'M'],
87+
['cvvCode' => 'N', 'expected' => 'N'],
88+
['cvvCode' => 'U', 'expected' => 'P'],
89+
['cvvCode' => 'I', 'expected' => 'P'],
90+
['cvvCode' => 'S', 'expected' => 'S'],
91+
['cvvCode' => 'A', 'expected' => ''],
92+
];
93+
}
94+
}

app/code/Magento/Braintree/etc/config.xml

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
<masked_fields>cvv,number</masked_fields>
4141
<privateInfoKeys>avsPostalCodeResponseCode,avsStreetAddressResponseCode,cvvResponseCode,processorAuthorizationCode,processorResponseCode,processorResponseText,liabilityShifted,liabilityShiftPossible,riskDataId,riskDataDecision</privateInfoKeys>
4242
<paymentInfoKeys>cc_type,cc_number,avsPostalCodeResponseCode,avsStreetAddressResponseCode,cvvResponseCode,processorAuthorizationCode,processorResponseCode,processorResponseText,liabilityShifted,liabilityShiftPossible,riskDataId,riskDataDecision</paymentInfoKeys>
43+
<avs_ems_adapter>Magento\Braintree\Model\AvsEmsCodeMapper</avs_ems_adapter>
44+
<cvv_ems_adapter>Magento\Braintree\Model\CvvEmsCodeMapper</cvv_ems_adapter>
4345
</braintree>
4446
<braintree_paypal>
4547
<model>BraintreePayPalFacade</model>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Payment\Api;
7+
8+
use Magento\Sales\Api\Data\OrderPaymentInterface;
9+
10+
/**
11+
* Payment provider codes verification interface.
12+
*
13+
* Custom payment methods might implement this interface to provide
14+
* specific mapping for payment methods, like AVS or CVV verification.
15+
* The payment methods can map payment method info from internal sources,
16+
* like additional information, to specific international codes.
17+
*
18+
* There are no default implementation of this interface, because code verification
19+
* depends on payment method integration specifics.
20+
*
21+
* @api
22+
*/
23+
interface PaymentVerificationInterface
24+
{
25+
/**
26+
* Gets payment provider verification code.
27+
* Throws an exception if provided payment method is different to verification implementation.
28+
*
29+
* @param OrderPaymentInterface $orderPayment
30+
* @return string
31+
* @throws \InvalidArgumentException
32+
*/
33+
public function getCode(OrderPaymentInterface $orderPayment);
34+
}

0 commit comments

Comments
 (0)