Skip to content

Commit 5efaca9

Browse files
authored
Merge pull request #4199 from magento-tango/PR-2.2-ALL
[TANGO] PR-2.2-ALL
2 parents 0175f09 + ba0c6d7 commit 5efaca9

File tree

4 files changed

+92
-17
lines changed

4 files changed

+92
-17
lines changed

app/code/Magento/Paypal/Model/Express.php

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717
use Magento\Store\Model\ScopeInterface;
1818

1919
/**
20-
* PayPal Express Module
20+
* PayPal Express Module.
21+
*
2122
* @method \Magento\Quote\Api\Data\PaymentMethodExtensionInterface getExtensionAttributes()
2223
* @SuppressWarnings(PHPMD.TooManyFields)
2324
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
25+
* @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
2426
*/
2527
class Express extends \Magento\Payment\Model\Method\AbstractMethod
2628
{
@@ -179,6 +181,11 @@ class Express extends \Magento\Payment\Model\Method\AbstractMethod
179181
*/
180182
protected $transactionBuilder;
181183

184+
/**
185+
* @var string
186+
*/
187+
private static $authorizationExpiredCode = 10601;
188+
182189
/**
183190
* @param \Magento\Framework\Model\Context $context
184191
* @param \Magento\Framework\Registry $registry
@@ -269,6 +276,7 @@ protected function _setApiProcessableErrors()
269276
ApiProcessableException::API_MAXIMUM_AMOUNT_FILTER_DECLINE,
270277
ApiProcessableException::API_OTHER_FILTER_DECLINE,
271278
ApiProcessableException::API_ADDRESS_MATCH_FAIL,
279+
self::$authorizationExpiredCode
272280
]
273281
);
274282
}
@@ -538,7 +546,17 @@ public function refund(\Magento\Payment\Model\InfoInterface $payment, $amount)
538546
*/
539547
public function cancel(\Magento\Payment\Model\InfoInterface $payment)
540548
{
541-
$this->void($payment);
549+
try {
550+
$this->void($payment);
551+
} catch (ApiProcessableException $e) {
552+
if ((int)$e->getCode() === self::$authorizationExpiredCode) {
553+
$payment->setTransactionId(null);
554+
$payment->setIsTransactionClosed(true);
555+
$payment->setShouldCloseParentTransaction(true);
556+
} else {
557+
throw $e;
558+
}
559+
}
542560

543561
return $this;
544562
}

app/code/Magento/Paypal/Model/Pro.php

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010

1111
use Magento\Paypal\Model\Api\AbstractApi;
1212
use Magento\Sales\Api\TransactionRepositoryInterface;
13-
use Magento\Paypal\Model\Info;
1413

1514
/**
16-
* PayPal Website Payments Pro implementation for payment method instances
15+
* PayPal Website Payments Pro implementation for payment method instances.
16+
*
1717
* This model was created because right now PayPal Direct and PayPal Express payment methods cannot have same abstract
1818
*/
1919
class Pro
@@ -149,7 +149,8 @@ public function getConfig()
149149
}
150150

151151
/**
152-
* API instance getter
152+
* API instance getter.
153+
*
153154
* Sets current store id to current config instance and passes it to API
154155
*
155156
* @return \Magento\Paypal\Model\Api\Nvp
@@ -231,19 +232,22 @@ public function importPaymentInfo(\Magento\Framework\DataObject $from, \Magento\
231232
public function void(\Magento\Framework\DataObject $payment)
232233
{
233234
$authTransactionId = $this->_getParentTransactionId($payment);
234-
if ($authTransactionId) {
235-
$api = $this->getApi();
236-
$api->setPayment($payment)->setAuthorizationId($authTransactionId)->callDoVoid();
237-
$this->importPaymentInfo($api, $payment);
238-
} else {
235+
if (empty($authTransactionId)) {
239236
throw new \Magento\Framework\Exception\LocalizedException(
240237
__('You need an authorization transaction to void.')
241238
);
242239
}
240+
241+
$api = $this->getApi();
242+
$api->setPayment($payment);
243+
$api->setAuthorizationId($authTransactionId);
244+
$api->callDoVoid();
245+
$this->importPaymentInfo($api, $payment);
243246
}
244247

245248
/**
246-
* Attempt to capture payment
249+
* Attempt to capture payment.
250+
*
247251
* Will return false if the payment is not supposed to be captured
248252
*
249253
* @param \Magento\Framework\DataObject $payment

app/code/Magento/Paypal/Test/Unit/Model/ExpressTest.php

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,31 @@
1212
use Magento\Payment\Model\InfoInterface;
1313
use Magento\Payment\Observer\AbstractDataAssignObserver;
1414
use Magento\Paypal\Model\Api\Nvp;
15+
use Magento\Paypal\Model\Api\ProcessableException;
1516
use Magento\Paypal\Model\Api\ProcessableException as ApiProcessableException;
1617
use Magento\Paypal\Model\Express;
1718
use Magento\Paypal\Model\Pro;
1819
use Magento\Quote\Api\Data\PaymentInterface;
1920
use Magento\Sales\Model\Order;
2021
use Magento\Sales\Model\Order\Payment;
2122
use Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface;
22-
use \PHPUnit_Framework_MockObject_MockObject as MockObject;
23+
use PHPUnit_Framework_MockObject_MockObject as MockObject;
2324

2425
/**
2526
* Class ExpressTest
2627
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2728
*/
2829
class ExpressTest extends \PHPUnit\Framework\TestCase
2930
{
31+
/**
32+
* @var string
33+
*/
34+
private static $authorizationExpiredCode = 10601;
35+
3036
/**
3137
* @var array
3238
*/
33-
protected $errorCodes = [
39+
private $errorCodes = [
3440
ApiProcessableException::API_INTERNAL_ERROR,
3541
ApiProcessableException::API_UNABLE_PROCESS_PAYMENT_ERROR_CODE,
3642
ApiProcessableException::API_DO_EXPRESS_CHECKOUT_FAIL,
@@ -40,7 +46,7 @@ class ExpressTest extends \PHPUnit\Framework\TestCase
4046
ApiProcessableException::API_COUNTRY_FILTER_DECLINE,
4147
ApiProcessableException::API_MAXIMUM_AMOUNT_FILTER_DECLINE,
4248
ApiProcessableException::API_OTHER_FILTER_DECLINE,
43-
ApiProcessableException::API_ADDRESS_MATCH_FAIL
49+
ApiProcessableException::API_ADDRESS_MATCH_FAIL,
4450
];
4551

4652
/**
@@ -80,6 +86,7 @@ class ExpressTest extends \PHPUnit\Framework\TestCase
8086

8187
protected function setUp()
8288
{
89+
$this->errorCodes[] = self::$authorizationExpiredCode;
8390
$this->checkoutSession = $this->createPartialMock(
8491
Session::class,
8592
['getPaypalTransactionData', 'setPaypalTransactionData']
@@ -104,16 +111,20 @@ protected function setUp()
104111
);
105112
$this->pro = $this->createPartialMock(
106113
Pro::class,
107-
['setMethod', 'getApi', 'importPaymentInfo', 'resetApi']
114+
['setMethod', 'getApi', 'importPaymentInfo', 'resetApi', 'void']
108115
);
109116
$this->eventManager = $this->getMockBuilder(ManagerInterface::class)
110117
->setMethods(['dispatch'])
111118
->getMockForAbstractClass();
112119

113-
$this->pro->expects($this->any())->method('getApi')->will($this->returnValue($this->nvp));
120+
$this->pro->method('getApi')
121+
->willReturn($this->nvp);
114122
$this->helper = new ObjectManager($this);
115123
}
116124

125+
/**
126+
* Tests setting the list of processable errors.
127+
*/
117128
public function testSetApiProcessableErrors()
118129
{
119130
$this->nvp->expects($this->once())->method('setProcessableErrors')->with($this->errorCodes);
@@ -128,6 +139,32 @@ public function testSetApiProcessableErrors()
128139
);
129140
}
130141

142+
/**
143+
* Tests canceling order payment when expired authorization generates exception on a client.
144+
*/
145+
public function testCancelWithExpiredAuthorizationTransaction()
146+
{
147+
$this->pro->method('void')
148+
->willThrowException(
149+
new ProcessableException(__('PayPal gateway has rejected request.'), null, 10601)
150+
);
151+
152+
$this->model = $this->helper->getObject(Express::class, ['data' => [$this->pro]]);
153+
/** @var Payment|MockObject $paymentModel */
154+
$paymentModel = $this->createMock(Payment::class);
155+
$paymentModel->expects($this->once())
156+
->method('setTransactionId')
157+
->with(null);
158+
$paymentModel->expects($this->once())
159+
->method('setIsTransactionClosed')
160+
->with(true);
161+
$paymentModel->expects($this->once())
162+
->method('setShouldCloseParentTransaction')
163+
->with(true);
164+
165+
$this->model->cancel($paymentModel);
166+
}
167+
131168
/**
132169
* Tests order payment action.
133170
*/
@@ -162,6 +199,11 @@ public function testOrder()
162199
static::assertEquals($this->model, $this->model->order($paymentModel, 12.3));
163200
}
164201

202+
/**
203+
* Tests data assigning.
204+
*
205+
* @throws \Magento\Framework\Exception\LocalizedException
206+
*/
165207
public function testAssignData()
166208
{
167209
$transportValue = 'something';

lib/web/mage/trim-input.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,20 @@ define([
4141
* @private
4242
*/
4343
_trimInput: function () {
44-
var input = this._getInputValue().trim();
44+
// Safari caret position workaround: storing carter position
45+
var caretStart, caretEnd, input;
46+
47+
caretStart = this.options.cache.input.get(0).selectionStart;
48+
caretEnd = this.options.cache.input.get(0).selectionEnd;
49+
50+
input = this._getInputValue().trim();
4551

4652
this.options.cache.input.val(input);
53+
54+
// Safari caret position workaround: setting caret position to previously stored values
55+
if (caretStart !== null && caretEnd !== null) {
56+
this.options.cache.input.get(0).setSelectionRange(caretStart, caretEnd);
57+
}
4758
},
4859

4960
/**

0 commit comments

Comments
 (0)