Skip to content

Commit 7b790d0

Browse files
committed
Merge branch 'MAGETWO-99094' of https://github.com/magento-mpi/magento2ce into pr_2019_04_17
2 parents e76579f + de36496 commit 7b790d0

File tree

2 files changed

+184
-1
lines changed

2 files changed

+184
-1
lines changed

app/code/Magento/Paypal/Model/Payflow/Service/Response/Transaction.php

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
* Copyright © Magento, Inc. All rights reserved.
44
* See COPYING.txt for license details.
55
*/
6+
declare(strict_types=1);
7+
68
namespace Magento\Paypal\Model\Payflow\Service\Response;
79

810
use Magento\Framework\DataObject;
11+
use Magento\Framework\Intl\DateTimeFactory;
912
use Magento\Payment\Model\Method\Logger;
1013
use Magento\Paypal\Model\Payflow\Service\Response\Handler\HandlerInterface;
1114
use Magento\Framework\Session\Generic;
@@ -18,6 +21,7 @@
1821

1922
/**
2023
* Class Transaction
24+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2125
*/
2226
class Transaction
2327
{
@@ -51,28 +55,36 @@ class Transaction
5155
*/
5256
private $logger;
5357

58+
/**
59+
* @var DateTimeFactory
60+
*/
61+
private $dateTimeFactory;
62+
5463
/**
5564
* @param Generic $sessionTransparent
5665
* @param CartRepositoryInterface $quoteRepository
5766
* @param Transparent $transparent
5867
* @param PaymentMethodManagementInterface $paymentManagement
5968
* @param HandlerInterface $errorHandler
6069
* @param Logger $logger
70+
* @param DateTimeFactory $dateTimeFactory
6171
*/
6272
public function __construct(
6373
Generic $sessionTransparent,
6474
CartRepositoryInterface $quoteRepository,
6575
Transparent $transparent,
6676
PaymentMethodManagementInterface $paymentManagement,
6777
HandlerInterface $errorHandler,
68-
Logger $logger
78+
Logger $logger,
79+
DateTimeFactory $dateTimeFactory
6980
) {
7081
$this->sessionTransparent = $sessionTransparent;
7182
$this->quoteRepository = $quoteRepository;
7283
$this->transparent = $transparent;
7384
$this->paymentManagement = $paymentManagement;
7485
$this->errorHandler = $errorHandler;
7586
$this->logger = $logger;
87+
$this->dateTimeFactory = $dateTimeFactory;
7688
}
7789

7890
/**
@@ -114,8 +126,45 @@ public function savePaymentInQuote($response)
114126
$payment->setData(OrderPaymentInterface::CC_TYPE, $response->getData(OrderPaymentInterface::CC_TYPE));
115127
$payment->setAdditionalInformation(Payflowpro::PNREF, $response->getData(Payflowpro::PNREF));
116128

129+
$expDate = $response->getData('expdate');
130+
$expMonth = $this->getCcExpMonth($expDate);
131+
$payment->setCcExpMonth($expMonth);
132+
$expYear = $this->getCcExpYear($expDate);
133+
$payment->setCcExpYear($expYear);
134+
117135
$this->errorHandler->handle($payment, $response);
118136

119137
$this->paymentManagement->set($quote->getId(), $payment);
120138
}
139+
140+
/**
141+
* Extracts expiration month from PayPal response expiration date.
142+
*
143+
* @param string $expDate format {MMYY}
144+
* @return int
145+
*/
146+
private function getCcExpMonth(string $expDate): int
147+
{
148+
return (int)substr($expDate, 0, 2);
149+
}
150+
151+
/**
152+
* Extracts expiration year from PayPal response expiration date.
153+
*
154+
* @param string $expDate format {MMYY}
155+
* @return int
156+
*/
157+
private function getCcExpYear(string $expDate): int
158+
{
159+
$last2YearDigits = (int)substr($expDate, 2, 2);
160+
$currentDate = $this->dateTimeFactory->create('now', new \DateTimeZone('UTC'));
161+
$first2YearDigits = (int)substr($currentDate->format('Y'), 0, 2);
162+
163+
// case when credit card expires at next century
164+
if ((int)$currentDate->format('y') > $last2YearDigits) {
165+
$first2YearDigits++;
166+
}
167+
168+
return 100 * $first2YearDigits + $last2YearDigits;
169+
}
121170
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Paypal\Controller\Transparent;
9+
10+
use Magento\Checkout\Model\Session;
11+
use Magento\Framework\Api\SearchCriteriaBuilder;
12+
use Magento\Framework\Exception\NoSuchEntityException;
13+
use Magento\Framework\Intl\DateTimeFactory;
14+
use Magento\Framework\Session\Generic as GenericSession;
15+
use Magento\Quote\Api\CartRepositoryInterface;
16+
use Magento\Quote\Api\Data\CartInterface;
17+
use Magento\Quote\Api\PaymentMethodManagementInterface;
18+
19+
/**
20+
* Tests PayPal transparent response controller.
21+
*/
22+
class ResponseTest extends \Magento\TestFramework\TestCase\AbstractController
23+
{
24+
/**
25+
* Tests setting credit card expiration month and year to payment from PayPal response.
26+
*
27+
* @param string $currentDateTime
28+
* @param string $paypalExpDate
29+
* @param string $expectedCcMonth
30+
* @param string $expectedCcYear
31+
* @throws NoSuchEntityException
32+
*
33+
* @magentoConfigFixture current_store payment/payflowpro/active 1
34+
* @magentoDataFixture Magento/Sales/_files/quote.php
35+
* @dataProvider paymentCcExpirationDateDataProvider
36+
*/
37+
public function testPaymentCcExpirationDate(
38+
string $currentDateTime,
39+
string $paypalExpDate,
40+
string $expectedCcMonth,
41+
string $expectedCcYear
42+
) {
43+
$reservedOrderId = 'test01';
44+
$postData = [
45+
'EXPDATE' => $paypalExpDate,
46+
'AMT' => '0.00',
47+
'RESPMSG' => 'Verified',
48+
'CVV2MATCH' => 'Y',
49+
'PNREF' => 'A10AAD866C87',
50+
'SECURETOKEN' => '3HYEHfG06skydAdBXbpIl8QJZ',
51+
'AVSDATA' => 'YNY',
52+
'RESULT' => '0',
53+
'IAVS' => 'N',
54+
'AVSADDR' => 'Y',
55+
'SECURETOKENID' => 'yqanLisRZbI0HAG8q3SbbKbhiwjNZAGf',
56+
];
57+
58+
$quote = $this->getQuote($reservedOrderId);
59+
$this->getRequest()->setPostValue($postData);
60+
61+
/** @var Session $checkoutSession */
62+
$checkoutSession = $this->_objectManager->get(GenericSession::class);
63+
$checkoutSession->setQuoteId($quote->getId());
64+
$this->setCurrentDateTime($currentDateTime);
65+
66+
$this->dispatch('paypal/transparent/response');
67+
68+
/** @var PaymentMethodManagementInterface $paymentManagment */
69+
$paymentManagment = $this->_objectManager->get(PaymentMethodManagementInterface::class);
70+
$payment = $paymentManagment->get($quote->getId());
71+
72+
$this->assertEquals($expectedCcMonth, $payment->getCcExpMonth());
73+
$this->assertEquals($expectedCcYear, $payment->getCcExpYear());
74+
}
75+
76+
/**
77+
* @return array
78+
*/
79+
public function paymentCcExpirationDateDataProvider(): array
80+
{
81+
return [
82+
'Expiration year in current century' => [
83+
'currentDateTime' => '2019-07-05 00:00:00',
84+
'paypalExpDate' => '0321',
85+
'expectedCcMonth' => 3,
86+
'expectedCcYear' => 2021
87+
],
88+
'Expiration year in next century' => [
89+
'currentDateTime' => '2099-01-01 00:00:00',
90+
'paypalExpDate' => '1002',
91+
'expectedCcMonth' => 10,
92+
'expectedCcYear' => 2102
93+
]
94+
];
95+
}
96+
97+
/**
98+
* Sets current date and time.
99+
*
100+
* @param string $date
101+
*/
102+
private function setCurrentDateTime(string $dateTime): void
103+
{
104+
$dateTime = new \DateTime($dateTime, new \DateTimeZone('UTC'));
105+
$dateTimeFactory = $this->getMockBuilder(DateTimeFactory::class)
106+
->disableOriginalConstructor()
107+
->getMock();
108+
109+
$dateTimeFactory->method('create')
110+
->willReturn($dateTime);
111+
112+
$this->_objectManager->addSharedInstance($dateTimeFactory, DateTimeFactory::class);
113+
}
114+
115+
/**
116+
* Gets quote by reserved order ID.
117+
*
118+
* @param string $reservedOrderId
119+
* @return CartInterface
120+
*/
121+
private function getQuote(string $reservedOrderId): CartInterface
122+
{
123+
$searchCriteria = $this->_objectManager->get(SearchCriteriaBuilder::class)
124+
->addFilter('reserved_order_id', $reservedOrderId)
125+
->create();
126+
127+
/** @var CartRepositoryInterface $quoteRepository */
128+
$quoteRepository = $this->_objectManager->get(CartRepositoryInterface::class);
129+
$items = $quoteRepository->getList($searchCriteria)
130+
->getItems();
131+
132+
return array_pop($items);
133+
}
134+
}

0 commit comments

Comments
 (0)