-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2681 from magento-tsg/2.3-develop-pr22
[TSG] Upporting for 2.3 (pr22) (2.3.0)
- Loading branch information
Showing
48 changed files
with
1,627 additions
and
858 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
app/code/Magento/Braintree/Gateway/Response/CancelDetailsHandler.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<?php | ||
/** | ||
* Copyright © Magento, Inc. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Magento\Braintree\Gateway\Response; | ||
|
||
use Magento\Braintree\Gateway\SubjectReader; | ||
use Magento\Payment\Gateway\Response\HandlerInterface; | ||
use Magento\Sales\Model\Order\Payment; | ||
|
||
/** | ||
* Handles response details for order cancellation request. | ||
*/ | ||
class CancelDetailsHandler implements HandlerInterface | ||
{ | ||
/** | ||
* @var SubjectReader | ||
*/ | ||
private $subjectReader; | ||
|
||
/** | ||
* @param SubjectReader $subjectReader | ||
*/ | ||
public function __construct(SubjectReader $subjectReader) | ||
{ | ||
$this->subjectReader = $subjectReader; | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function handle(array $handlingSubject, array $response) | ||
{ | ||
$paymentDO = $this->subjectReader->readPayment($handlingSubject); | ||
/** @var Payment $orderPayment */ | ||
$orderPayment = $paymentDO->getPayment(); | ||
$orderPayment->setIsTransactionClosed(true); | ||
$orderPayment->setShouldCloseParentTransaction(true); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
90 changes: 90 additions & 0 deletions
90
app/code/Magento/Braintree/Gateway/Validator/CancelResponseValidator.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
<?php | ||
/** | ||
* Copyright © Magento, Inc. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Magento\Braintree\Gateway\Validator; | ||
|
||
use Braintree\Error\ErrorCollection; | ||
use Braintree\Error\Validation; | ||
use Magento\Payment\Gateway\Validator\AbstractValidator; | ||
use Magento\Payment\Gateway\Validator\ResultInterface; | ||
use Magento\Payment\Gateway\Validator\ResultInterfaceFactory; | ||
use Magento\Braintree\Gateway\SubjectReader; | ||
|
||
/** | ||
* Decorates the general response validator to handle specific cases. | ||
* | ||
* This validator decorates the general response validator to handle specific cases like | ||
* an expired or already voided on Braintree side authorization transaction. | ||
*/ | ||
class CancelResponseValidator extends AbstractValidator | ||
{ | ||
/** | ||
* @var int | ||
*/ | ||
private static $acceptableTransactionCode = 91504; | ||
|
||
/** | ||
* @var GeneralResponseValidator | ||
*/ | ||
private $generalResponseValidator; | ||
|
||
/** | ||
* @var SubjectReader | ||
*/ | ||
private $subjectReader; | ||
|
||
/** | ||
* @param ResultInterfaceFactory $resultFactory | ||
* @param GeneralResponseValidator $generalResponseValidator | ||
* @param SubjectReader $subjectReader | ||
*/ | ||
public function __construct( | ||
ResultInterfaceFactory $resultFactory, | ||
GeneralResponseValidator $generalResponseValidator, | ||
SubjectReader $subjectReader | ||
) { | ||
parent::__construct($resultFactory); | ||
$this->generalResponseValidator = $generalResponseValidator; | ||
$this->subjectReader = $subjectReader; | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function validate(array $validationSubject): ResultInterface | ||
{ | ||
$result = $this->generalResponseValidator->validate($validationSubject); | ||
if (!$result->isValid()) { | ||
$response = $this->subjectReader->readResponseObject($validationSubject); | ||
if ($this->isErrorAcceptable($response->errors)) { | ||
$result = $this->createResult(true, [__('Transaction is cancelled offline.')]); | ||
} | ||
} | ||
|
||
return $result; | ||
} | ||
|
||
/** | ||
* Checks if error collection has an acceptable error code. | ||
* | ||
* @param ErrorCollection $errorCollection | ||
* @return bool | ||
*/ | ||
private function isErrorAcceptable(ErrorCollection $errorCollection): bool | ||
{ | ||
$errors = $errorCollection->deepAll(); | ||
// there is should be only one acceptable error | ||
if (count($errors) > 1) { | ||
return false; | ||
} | ||
|
||
/** @var Validation $error */ | ||
$error = array_pop($errors); | ||
|
||
return (int)$error->code === self::$acceptableTransactionCode; | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
app/code/Magento/Braintree/Test/Unit/Gateway/Response/CancelDetailsHandlerTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
<?php | ||
/** | ||
* Copyright © Magento, Inc. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Magento\Braintree\Test\Unit\Gateway\Response; | ||
|
||
use Magento\Braintree\Gateway\Response\CancelDetailsHandler; | ||
use Magento\Braintree\Gateway\SubjectReader; | ||
use Magento\Payment\Gateway\Data\OrderAdapterInterface; | ||
use Magento\Payment\Gateway\Data\PaymentDataObject; | ||
use Magento\Sales\Model\Order\Payment; | ||
use PHPUnit\Framework\TestCase; | ||
use PHPUnit_Framework_MockObject_MockObject as MockObject; | ||
|
||
/** | ||
* Tests \Magento\Braintree\Gateway\Response\CancelDetailsHandler. | ||
*/ | ||
class CancelDetailsHandlerTest extends TestCase | ||
{ | ||
/** | ||
* @var CancelDetailsHandler | ||
*/ | ||
private $handler; | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
protected function setUp() | ||
{ | ||
$this->handler = new CancelDetailsHandler(new SubjectReader()); | ||
} | ||
|
||
/** | ||
* Checks a case when cancel handler closes the current and parent transactions. | ||
* | ||
* @return void | ||
*/ | ||
public function testHandle(): void | ||
{ | ||
/** @var OrderAdapterInterface|MockObject $order */ | ||
$order = $this->getMockForAbstractClass(OrderAdapterInterface::class); | ||
/** @var Payment|MockObject $payment */ | ||
$payment = $this->getMockBuilder(Payment::class) | ||
->disableOriginalConstructor() | ||
->setMethods(['setOrder']) | ||
->getMock(); | ||
|
||
$paymentDO = new PaymentDataObject($order, $payment); | ||
$response = [ | ||
'payment' => $paymentDO, | ||
]; | ||
|
||
$this->handler->handle($response, []); | ||
|
||
self::assertTrue($payment->getIsTransactionClosed(), 'The current transaction should be closed.'); | ||
self::assertTrue($payment->getShouldCloseParentTransaction(), 'The parent transaction should be closed.'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
*/ | ||
namespace Magento\Braintree\Test\Unit\Gateway; | ||
|
||
use Braintree\Result\Successful; | ||
use Braintree\Transaction; | ||
use Magento\Braintree\Gateway\SubjectReader; | ||
|
||
|
@@ -18,6 +19,9 @@ class SubjectReaderTest extends \PHPUnit\Framework\TestCase | |
*/ | ||
private $subjectReader; | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
protected function setUp() | ||
{ | ||
$this->subjectReader = new SubjectReader(); | ||
|
@@ -27,67 +31,137 @@ protected function setUp() | |
* @covers \Magento\Braintree\Gateway\SubjectReader::readCustomerId | ||
* @expectedException \InvalidArgumentException | ||
* @expectedExceptionMessage The "customerId" field does not exists | ||
* @return void | ||
*/ | ||
public function testReadCustomerIdWithException() | ||
public function testReadCustomerIdWithException(): void | ||
{ | ||
$this->subjectReader->readCustomerId([]); | ||
} | ||
|
||
/** | ||
* @covers \Magento\Braintree\Gateway\SubjectReader::readCustomerId | ||
* @return void | ||
*/ | ||
public function testReadCustomerId() | ||
public function testReadCustomerId(): void | ||
{ | ||
$customerId = 1; | ||
static::assertEquals($customerId, $this->subjectReader->readCustomerId(['customer_id' => $customerId])); | ||
$this->assertEquals($customerId, $this->subjectReader->readCustomerId(['customer_id' => $customerId])); | ||
} | ||
|
||
/** | ||
* @covers \Magento\Braintree\Gateway\SubjectReader::readPublicHash | ||
* @expectedException \InvalidArgumentException | ||
* @expectedExceptionMessage The "public_hash" field does not exists | ||
* @return void | ||
*/ | ||
public function testReadPublicHashWithException() | ||
public function testReadPublicHashWithException(): void | ||
{ | ||
$this->subjectReader->readPublicHash([]); | ||
} | ||
|
||
/** | ||
* @covers \Magento\Braintree\Gateway\SubjectReader::readPublicHash | ||
* @return void | ||
*/ | ||
public function testReadPublicHash() | ||
public function testReadPublicHash(): void | ||
{ | ||
$hash = 'fj23djf2o1fd'; | ||
static::assertEquals($hash, $this->subjectReader->readPublicHash(['public_hash' => $hash])); | ||
$this->assertEquals($hash, $this->subjectReader->readPublicHash(['public_hash' => $hash])); | ||
} | ||
|
||
/** | ||
* @covers \Magento\Braintree\Gateway\SubjectReader::readPayPal | ||
* @expectedException \InvalidArgumentException | ||
* @expectedExceptionMessage Transaction has't paypal attribute | ||
* @return void | ||
*/ | ||
public function testReadPayPalWithException() | ||
public function testReadPayPalWithException(): void | ||
{ | ||
$transaction = Transaction::factory([ | ||
'id' => 'u38rf8kg6vn' | ||
'id' => 'u38rf8kg6vn', | ||
]); | ||
$this->subjectReader->readPayPal($transaction); | ||
} | ||
|
||
/** | ||
* @covers \Magento\Braintree\Gateway\SubjectReader::readPayPal | ||
* @return void | ||
*/ | ||
public function testReadPayPal() | ||
public function testReadPayPal(): void | ||
{ | ||
$paypal = [ | ||
'paymentId' => '3ek7dk7fn0vi1', | ||
'payerEmail' => '[email protected]' | ||
'payerEmail' => '[email protected]', | ||
]; | ||
$transaction = Transaction::factory([ | ||
'id' => '4yr95vb', | ||
'paypal' => $paypal | ||
'paypal' => $paypal, | ||
]); | ||
|
||
static::assertEquals($paypal, $this->subjectReader->readPayPal($transaction)); | ||
$this->assertEquals($paypal, $this->subjectReader->readPayPal($transaction)); | ||
} | ||
|
||
/** | ||
* Checks a case when subject reader retrieves successful Braintree transaction. | ||
* | ||
* @return void | ||
*/ | ||
public function testReadTransaction(): void | ||
{ | ||
$transaction = Transaction::factory(['id' => 1]); | ||
$response = [ | ||
'object' => new Successful($transaction, 'transaction'), | ||
]; | ||
$actual = $this->subjectReader->readTransaction($response); | ||
|
||
$this->assertSame($transaction, $actual); | ||
} | ||
|
||
/** | ||
* Checks a case when subject reader retrieves invalid data instead transaction details. | ||
* | ||
* @param array $response | ||
* @param string $expectedMessage | ||
* @dataProvider invalidTransactionResponseDataProvider | ||
* @expectedException \InvalidArgumentException | ||
* @return void | ||
*/ | ||
public function testReadTransactionWithInvalidResponse(array $response, string $expectedMessage): void | ||
{ | ||
$this->expectExceptionMessage($expectedMessage); | ||
$this->subjectReader->readTransaction($response); | ||
} | ||
|
||
/** | ||
* Gets list of variations with invalid subject data. | ||
* | ||
* @return array | ||
*/ | ||
public function invalidTransactionResponseDataProvider(): array | ||
{ | ||
$transaction = new \stdClass(); | ||
$response = new \stdClass(); | ||
$response->transaction = $transaction; | ||
|
||
return [ | ||
[ | ||
'response' => [ | ||
'object' => [], | ||
], | ||
'expectedMessage' => 'Response object does not exist.', | ||
], | ||
[ | ||
'response' => [ | ||
'object' => new \stdClass(), | ||
], | ||
'expectedMessage' => 'The object is not a class \Braintree\Transaction.', | ||
], | ||
[ | ||
'response' => [ | ||
'object' => $response, | ||
], | ||
'expectedMessage' => 'The object is not a class \Braintree\Transaction.', | ||
], | ||
]; | ||
} | ||
} |
Oops, something went wrong.