From a425b7092fbd9c83a9e2dd4b464e7cf3bd8ed9c9 Mon Sep 17 00:00:00 2001 From: khushboos Date: Tue, 15 Oct 2024 16:35:16 +0200 Subject: [PATCH 01/25] Handling Refund Delay and Order Cancellation Issues when using Gift Card + redirected Payment method --- Helper/PaymentResponseHandler.php | 83 ++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/Helper/PaymentResponseHandler.php b/Helper/PaymentResponseHandler.php index dd5950ff6..d6d4d57a6 100644 --- a/Helper/PaymentResponseHandler.php +++ b/Helper/PaymentResponseHandler.php @@ -11,7 +11,10 @@ namespace Adyen\Payment\Helper; +use Adyen\Model\Checkout\CancelOrderRequest; +use Adyen\Payment\Helper\Config as Config; use Adyen\Payment\Logger\AdyenLogger; +use Adyen\Payment\Model\ResourceModel\PaymentResponse\CollectionFactory as PaymentResponseCollectionFactory; use Exception; use Magento\Framework\Exception\AlreadyExistsException; use Magento\Framework\Exception\InputException; @@ -21,6 +24,8 @@ use Magento\Sales\Model\OrderRepository; use Magento\Sales\Model\ResourceModel\Order; use Magento\Sales\Model\Order as OrderModel; +use Adyen\Payment\Helper\Data as Data; +use Magento\Framework\Mail\Exception\InvalidArgumentException; class PaymentResponseHandler { @@ -57,6 +62,8 @@ class PaymentResponseHandler private OrderRepository $orderRepository; private HistoryFactory $orderHistoryFactory; private StateData $stateDataHelper; + private PaymentResponseCollectionFactory $paymentResponseCollectionFactory; + private Config $configHelper; public function __construct( AdyenLogger $adyenLogger, @@ -67,7 +74,9 @@ public function __construct( \Adyen\Payment\Helper\Order $orderHelper, OrderRepository $orderRepository, HistoryFactory $orderHistoryFactory, - StateData $stateDataHelper + StateData $stateDataHelper, + PaymentResponseCollectionFactory $paymentResponseCollectionFactory, + Config $configHelper ) { $this->adyenLogger = $adyenLogger; $this->vaultHelper = $vaultHelper; @@ -78,6 +87,8 @@ public function __construct( $this->orderRepository = $orderRepository; $this->orderHistoryFactory = $orderHistoryFactory; $this->stateDataHelper = $stateDataHelper; + $this->paymentResponseCollectionFactory = $paymentResponseCollectionFactory; + $this->configHelper = $configHelper; } public function formatPaymentResponse( @@ -279,6 +290,63 @@ public function handlePaymentsDetailsResponse( break; case self::REFUSED: case self::CANCELLED: + $getGiftcardDetails = $this->hasActiveGiftCardPayments( + $order, + $paymentsDetailsResponse['merchantReference'] + ); + if (!empty($getGiftcardDetails)) { + //Cancel the Authorised Payments + $storeId = $order->getStoreId(); + $client = $this->dataHelper->initializeAdyenClient($storeId); + $service = $this->dataHelper->initializeOrdersApi($client); + foreach ($getGiftcardDetails as $giftcardData) { + try { + // Decode JSON response and validate it + $response = json_decode($giftcardData['response'], true); + if (json_last_error() !== JSON_ERROR_NONE || !isset($response['order'])) { + throw new InvalidArgumentException('Invalid giftcard response data'); + } + + // Extract order data and PSPRef + $orderData = $response['order']['orderData'] ?? null; + $pspReference = $response['order']['pspReference'] ?? null; + + if (!$orderData || !$pspReference) { + throw new InvalidArgumentException('Missing orderData or pspReference in the response'); + } + + // Prepare cancel request + $merchantAccount = $this->configHelper->getAdyenAbstractConfigData("merchant_account", $storeId); + $cancelRequest = [ + 'order' => [ + 'pspReference' => $pspReference, + 'orderData' => $orderData, + ], + 'merchantAccount' => $merchantAccount, + ]; + + // Call the cancel service + $cancelResponse = $service->cancelOrder(new CancelOrderRequest($cancelRequest)); + $response = $cancelResponse->toArray(); + + if (is_null($response['resultCode'])) { + // In case the result is unknown we log the request and don't update the history + $this->adyenLogger->error( + "Unexpected result query parameter for cancel order request. Response: " . json_encode($response) + ); + + return false; + } + + } catch (\Exception $e) { + // Log the error with relevant information for debugging + $this->adyenLogger->error('Error canceling partial payments', [ + 'exception' => $e->getMessage(), + 'giftcardData' => $giftcardData, + ]); + } + } + } // Cancel order in case result is refused if (null !== $order) { // Check if the current state allows for changing to new for cancellation @@ -341,4 +409,17 @@ private function isValidMerchantReference(array $paymentsDetailsResponse, OrderI return true; } + + // Method to check for existing Gift Card payments + private function hasActiveGiftCardPayments(OrderInterface $order, $merchantReference) + { + $paymentResponseCollection = $this->paymentResponseCollectionFactory->create() + ->addFieldToFilter('merchant_reference', $merchantReference) + ->addFieldToFilter('result_code', 'Authorised'); + + if ($paymentResponseCollection->getSize() > 0) { + return $paymentResponseCollection->getData(); + } + return ''; + } } From fc12873e1c1248f2a9149a1076aa53985dca5f83 Mon Sep 17 00:00:00 2001 From: khushboos Date: Wed, 16 Oct 2024 16:04:03 +0200 Subject: [PATCH 02/25] solving code sniffer issues --- Helper/PaymentResponseHandler.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Helper/PaymentResponseHandler.php b/Helper/PaymentResponseHandler.php index d6d4d57a6..bf346c263 100644 --- a/Helper/PaymentResponseHandler.php +++ b/Helper/PaymentResponseHandler.php @@ -337,7 +337,6 @@ public function handlePaymentsDetailsResponse( return false; } - } catch (\Exception $e) { // Log the error with relevant information for debugging $this->adyenLogger->error('Error canceling partial payments', [ From 8c7ea50ca5635edc6dc3c9eb89df42a21b38340f Mon Sep 17 00:00:00 2001 From: khushboos Date: Thu, 17 Oct 2024 10:36:51 +0200 Subject: [PATCH 03/25] Updating unit test --- .../Helper/PaymentResponseHandlerTest.php | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 6f88669d5..eb227e969 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -29,6 +29,9 @@ use Magento\Sales\Model\OrderRepository; use Magento\Sales\Model\Order\Status\HistoryFactory; use Adyen\Payment\Helper\StateData; +use Adyen\Payment\Model\ResourceModel\PaymentResponse\CollectionFactory as PaymentResponseCollectionFactory; +use Adyen\Payment\Helper\Config as Config; +use \Magento\Framework\Data\Collection\AbstractDb; class PaymentResponseHandlerTest extends AbstractAdyenTestCase { @@ -61,6 +64,32 @@ protected function setUp(): void 'create' ]); $this->stateDataHelperMock = $this->createMock(StateData::class); + $this->paymentResponseCollectionFactoryMock = $this->createMock(PaymentResponseCollectionFactory::class); + $this->configHelperMock = $this->createMock(Config::class); + + // Mock for PaymentResponseCollection + $this->paymentResponseCollectionMock = $this->createMock(AbstractDb::class); + + // Mock PaymentResponseCollectionFactory to return the mocked collection + $this->paymentResponseCollectionFactoryMock->method('create') + ->willReturn($this->paymentResponseCollectionMock); + + // Mock addFieldToFilter behavior + $this->paymentResponseCollectionMock->method('addFieldToFilter') + ->willReturnSelf(); + + // Mock getSize to return a desired value + $this->paymentResponseCollectionMock->method('getSize') + ->willReturn(1); // Adjust based on your test case logic + + // Mock getData to return some dummy data + $this->paymentResponseCollectionMock->method('getData') + ->willReturn([['field' => 'value']]); + + + + + $orderHistory = $this->createMock(History::class); $orderHistory->method('setStatus')->willReturnSelf(); @@ -74,7 +103,7 @@ protected function setUp(): void $this->orderMock->method('getStatus')->willReturn('pending'); $this->orderMock->method('getIncrementId')->willReturn('00123456'); - $this->orderHelperMock->method('setStatusOrderCreation')->willReturn( $this->orderMock); + $this->orderHelperMock->method('setStatusOrderCreation')->willReturn($this->orderMock); $this->paymentResponseHandler = new PaymentResponseHandler( $this->adyenLoggerMock, @@ -85,7 +114,9 @@ protected function setUp(): void $this->orderHelperMock, $this->orderRepositoryMock, $this->orderHistoryFactoryMock, - $this->stateDataHelperMock + $this->stateDataHelperMock, + $this->paymentResponseCollectionFactoryMock, + $this->configHelperMock ); } From 3f921bc137bb33c58e0abcebf5f0d44d63d50844 Mon Sep 17 00:00:00 2001 From: khushboos Date: Thu, 17 Oct 2024 10:50:58 +0200 Subject: [PATCH 04/25] Updating the composer version from V1 to 2 to solve the failing pipeline issue --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 462312b47..de79e4ac3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,7 +24,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} - tools: composer:v1 + tools: composer:2 - name: Test plugin installation run: | From 60b0bae6696949bc4e65bf928a51a4abe84a8e5e Mon Sep 17 00:00:00 2001 From: khushboos Date: Thu, 17 Oct 2024 10:55:48 +0200 Subject: [PATCH 05/25] Updating config to allow plugins --- composer.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/composer.json b/composer.json index 3f6ebb8cd..cc9952d42 100755 --- a/composer.json +++ b/composer.json @@ -43,5 +43,11 @@ "Composer\\Config::disableProcessTimeout", "vendor/bin/phpunit -c Test/phpunit.xml" ] + }, + "config": { + "allow-plugins": { + "magento/composer-dependency-version-audit-plugin": true, + "dealerdirect/phpcodesniffer-composer-installer": true + } } } From a59d157b294f59c6a679572eef8e7be9da512488 Mon Sep 17 00:00:00 2001 From: khushboos Date: Thu, 17 Oct 2024 11:12:41 +0200 Subject: [PATCH 06/25] Updating unit test --- Test/Unit/Helper/PaymentResponseHandlerTest.php | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index eb227e969..1eff8d7f5 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -29,7 +29,7 @@ use Magento\Sales\Model\OrderRepository; use Magento\Sales\Model\Order\Status\HistoryFactory; use Adyen\Payment\Helper\StateData; -use Adyen\Payment\Model\ResourceModel\PaymentResponse\CollectionFactory as PaymentResponseCollectionFactory; +use Adyen\Payment\Model\ResourceModel\PaymentResponse\CollectionFactory; use Adyen\Payment\Helper\Config as Config; use \Magento\Framework\Data\Collection\AbstractDb; @@ -46,7 +46,6 @@ class PaymentResponseHandlerTest extends AbstractAdyenTestCase private $orderRepositoryMock; private $orderHistoryFactoryMock; private $stateDataHelperMock; - private $paymentResponseHandler; protected function setUp(): void @@ -64,7 +63,7 @@ protected function setUp(): void 'create' ]); $this->stateDataHelperMock = $this->createMock(StateData::class); - $this->paymentResponseCollectionFactoryMock = $this->createMock(PaymentResponseCollectionFactory::class); + $this->paymentResponseCollectionFactoryMock = $this->createMock(CollectionFactory::class); $this->configHelperMock = $this->createMock(Config::class); // Mock for PaymentResponseCollection @@ -86,11 +85,6 @@ protected function setUp(): void $this->paymentResponseCollectionMock->method('getData') ->willReturn([['field' => 'value']]); - - - - - $orderHistory = $this->createMock(History::class); $orderHistory->method('setStatus')->willReturnSelf(); $orderHistory->method('setComment')->willReturnSelf(); From 37772dcbfdb9180d2ec49c8094e3169c85746c07 Mon Sep 17 00:00:00 2001 From: khushboos Date: Thu, 17 Oct 2024 13:56:43 +0200 Subject: [PATCH 07/25] Updating unit test --- .../Helper/PaymentResponseHandlerTest.php | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 1eff8d7f5..288aee3c0 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -10,8 +10,6 @@ */ namespace Adyen\Payment\Test\Unit\Helper; -namespace Adyen\Payment\Test\Unit\Helper; - use Adyen\Payment\Helper\PaymentResponseHandler; use Adyen\Payment\Logger\AdyenLogger; use Adyen\Payment\Helper\Vault; @@ -29,9 +27,9 @@ use Magento\Sales\Model\OrderRepository; use Magento\Sales\Model\Order\Status\HistoryFactory; use Adyen\Payment\Helper\StateData; +use Adyen\Payment\Model\ResourceModel\PaymentResponse\Collection; use Adyen\Payment\Model\ResourceModel\PaymentResponse\CollectionFactory; use Adyen\Payment\Helper\Config as Config; -use \Magento\Framework\Data\Collection\AbstractDb; class PaymentResponseHandlerTest extends AbstractAdyenTestCase { @@ -63,26 +61,23 @@ protected function setUp(): void 'create' ]); $this->stateDataHelperMock = $this->createMock(StateData::class); - $this->paymentResponseCollectionFactoryMock = $this->createMock(CollectionFactory::class); $this->configHelperMock = $this->createMock(Config::class); - // Mock for PaymentResponseCollection - $this->paymentResponseCollectionMock = $this->createMock(AbstractDb::class); - + $this->paymentResponseMockForFactory = $this->createMock(Collection::class); // Mock PaymentResponseCollectionFactory to return the mocked collection - $this->paymentResponseCollectionFactoryMock->method('create') - ->willReturn($this->paymentResponseCollectionMock); + $this->paymentResponseCollectionFactoryMock = $this->createGeneratedMock(CollectionFactory::class, ['create']); + $this->paymentResponseCollectionFactoryMock->method('create')->willReturn($this->paymentResponseMockForFactory); // Mock addFieldToFilter behavior - $this->paymentResponseCollectionMock->method('addFieldToFilter') + $this->paymentResponseMockForFactory->method('addFieldToFilter') ->willReturnSelf(); // Mock getSize to return a desired value - $this->paymentResponseCollectionMock->method('getSize') + $this->paymentResponseMockForFactory->method('getSize') ->willReturn(1); // Adjust based on your test case logic // Mock getData to return some dummy data - $this->paymentResponseCollectionMock->method('getData') + $this->paymentResponseMockForFactory->method('getData') ->willReturn([['field' => 'value']]); $orderHistory = $this->createMock(History::class); From 569ccf8647c4be707b34639f6897851d5c3828b3 Mon Sep 17 00:00:00 2001 From: khushboos Date: Fri, 18 Oct 2024 10:09:46 +0200 Subject: [PATCH 08/25] Updating unit test --- Helper/PaymentResponseHandler.php | 3 +- .../Helper/PaymentResponseHandlerTest.php | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/Helper/PaymentResponseHandler.php b/Helper/PaymentResponseHandler.php index bf346c263..81963ab05 100644 --- a/Helper/PaymentResponseHandler.php +++ b/Helper/PaymentResponseHandler.php @@ -291,7 +291,6 @@ public function handlePaymentsDetailsResponse( case self::REFUSED: case self::CANCELLED: $getGiftcardDetails = $this->hasActiveGiftCardPayments( - $order, $paymentsDetailsResponse['merchantReference'] ); if (!empty($getGiftcardDetails)) { @@ -410,7 +409,7 @@ private function isValidMerchantReference(array $paymentsDetailsResponse, OrderI } // Method to check for existing Gift Card payments - private function hasActiveGiftCardPayments(OrderInterface $order, $merchantReference) + private function hasActiveGiftCardPayments($merchantReference) { $paymentResponseCollection = $this->paymentResponseCollectionFactory->create() ->addFieldToFilter('merchant_reference', $merchantReference) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 288aee3c0..5bb9739bd 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -30,6 +30,7 @@ use Adyen\Payment\Model\ResourceModel\PaymentResponse\Collection; use Adyen\Payment\Model\ResourceModel\PaymentResponse\CollectionFactory; use Adyen\Payment\Helper\Config as Config; +use ReflectionClass; class PaymentResponseHandlerTest extends AbstractAdyenTestCase { @@ -475,4 +476,38 @@ public function testHandlePaymentsDetailsResponseInvalidMerchantReference(){ $this->assertFalse($result); } + + public function testHandlePaymentsDetailsResponseValidMerchantReference() + { + $paymentsDetailsResponse = [ + 'resultCode' => PaymentResponseHandler::AUTHORISED, + 'pspReference' => 'ABC123456789', + 'paymentMethod' => [ + 'brand' => 'ideal' + ], + 'merchantReference' => '00123456' // assuming this is a valid reference + ]; + // Mock the isValidMerchantReference to return true + $reflectionClass = new ReflectionClass(PaymentResponseHandler::class); + $method = $reflectionClass->getMethod('isValidMerchantReference'); + $method->setAccessible(true); + $isValidMerchantReference = $method->invokeArgs($this->paymentResponseHandler, [$paymentsDetailsResponse,$this->orderMock]); + $this->assertTrue($isValidMerchantReference); + } + + public function testPaymentDetailsCallFailureLogsError() + { + $resultCode = 'some_result_code'; + $paymentsDetailsResponse = ['error' => 'some error message']; + + // Expect the logger to be called with the specific message + $this->adyenLoggerMock->expects($this->once()) + ->method('error'); + + // Call the method that triggers the logging, e.g., handlePaymentDetailsFailure() + $this->paymentResponseHandler->handlePaymentsDetailsResponse( + $paymentsDetailsResponse, + $this->orderMock + ); + } } From 85f37c3ac2ff44d2bed624f421bf9262b1c483e1 Mon Sep 17 00:00:00 2001 From: khushboos Date: Fri, 18 Oct 2024 11:01:36 +0200 Subject: [PATCH 09/25] Updating unit test --- .../Helper/PaymentResponseHandlerTest.php | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 5bb9739bd..00b193926 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -510,4 +510,42 @@ public function testPaymentDetailsCallFailureLogsError() $this->orderMock ); } + + public function testLogsErrorAndReturnsFalseForUnknownResult() + { + // Arrange + $paymentsDetailsResponse = [ + 'merchantReference' => '00123456' + ]; + + // Mock the logger to expect an error to be logged + $this->adyenLoggerMock->expects($this->once()) + ->method('error') + ->with($this->stringContains('Unexpected result query parameter. Response: ' . json_encode($paymentsDetailsResponse))); + + // Act: Call the method that will trigger the unexpected result handling + $result = $this->paymentResponseHandler->handlePaymentsDetailsResponse($paymentsDetailsResponse, $this->orderMock); + + // Assert: Ensure the method returned false + $this->assertFalse($result); + } + + public function testOrderStatusUpdateWhenResponseIsValid() + { + $paymentsDetailsResponse = [ + 'merchantReference' => '00123456', + 'resultCode' => 'AUTHORISED' + ]; + + $this->orderMock->expects($this->once()) + ->method('getState') + ->willReturn('pending_payment'); + + // Mock the order repository to save the order + $this->orderRepositoryMock->expects($this->once()) + ->method('save') + ->with($this->orderMock); + + $this->paymentResponseHandler->handlePaymentsDetailsResponse($paymentsDetailsResponse, $this->orderMock); + } } From ec5f01455642d998d11c6ad61e583f7277825a91 Mon Sep 17 00:00:00 2001 From: khushboos Date: Fri, 18 Oct 2024 11:34:52 +0200 Subject: [PATCH 10/25] Updating unit test for asserting return from private methods --- .../Helper/PaymentResponseHandlerTest.php | 60 +++++++++++++++---- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 00b193926..bdb5279f4 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -10,6 +10,7 @@ */ namespace Adyen\Payment\Test\Unit\Helper; +use Adyen\Client; use Adyen\Payment\Helper\PaymentResponseHandler; use Adyen\Payment\Logger\AdyenLogger; use Adyen\Payment\Helper\Vault; @@ -69,18 +70,9 @@ protected function setUp(): void $this->paymentResponseCollectionFactoryMock = $this->createGeneratedMock(CollectionFactory::class, ['create']); $this->paymentResponseCollectionFactoryMock->method('create')->willReturn($this->paymentResponseMockForFactory); - // Mock addFieldToFilter behavior - $this->paymentResponseMockForFactory->method('addFieldToFilter') - ->willReturnSelf(); - - // Mock getSize to return a desired value - $this->paymentResponseMockForFactory->method('getSize') - ->willReturn(1); // Adjust based on your test case logic - - // Mock getData to return some dummy data - $this->paymentResponseMockForFactory->method('getData') - ->willReturn([['field' => 'value']]); - + $this->paymentResponseMockForFactory->expects($this->any()) + ->method('addFieldToFilter') + ->willReturn($this->paymentResponseMockForFactory); $orderHistory = $this->createMock(History::class); $orderHistory->method('setStatus')->willReturnSelf(); $orderHistory->method('setComment')->willReturnSelf(); @@ -548,4 +540,48 @@ public function testOrderStatusUpdateWhenResponseIsValid() $this->paymentResponseHandler->handlePaymentsDetailsResponse($paymentsDetailsResponse, $this->orderMock); } + + public function testHasActiveGiftCardPayments() + { + + // Mock the addFieldToFilter method to return the collection itself for chaining + + + // Mock getSize to simulate an authorized gift card payment + $this->paymentResponseMockForFactory->expects($this->any()) + ->method('getSize') + ->willReturn(1); // Simulate there is at least one record + + // Mock getData to return the desired array of data from the database + $this->paymentResponseMockForFactory->expects($this->any()) + ->method('getData') + ->willReturn([ + ['merchant_reference' => '12345', 'result_code' => 'Authorised'] + ]); + + $this->paymentResponseCollectionFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->paymentResponseMockForFactory); + + // Create an instance of the class that has the private method + $class = new \ReflectionClass(PaymentResponseHandler::class); + $instance = $class->newInstanceWithoutConstructor(); + + // Inject the mocked factory into the instance if necessary + $property = $class->getProperty('paymentResponseCollectionFactory'); + $property->setAccessible(true); + $property->setValue($instance, $this->paymentResponseCollectionFactoryMock); + + // Use Reflection to access the private method + $method = $class->getMethod('hasActiveGiftCardPayments'); + $method->setAccessible(true); + + // Call the private method with the required parameters + $result = $method->invoke($instance, '12345'); + + // Assert the expected result + $this->assertEquals([ + ['merchant_reference' => '12345', 'result_code' => 'Authorised'] + ], $result); + } } From ad67f207f40a61121a6edb9ddc141674f8c11f48 Mon Sep 17 00:00:00 2001 From: khushboos Date: Fri, 18 Oct 2024 15:05:40 +0200 Subject: [PATCH 11/25] Updating unit test for asserting return from private methods --- .../Helper/PaymentResponseHandlerTest.php | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index bdb5279f4..d66293cce 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -387,7 +387,8 @@ private static function handlePaymentsDetailsActionCancelledOrRefusedProvider(): { return [ ['resultCode' => PaymentResponseHandler::REFUSED], - ['resultCode' => PaymentResponseHandler::CANCELLED] + ['resultCode' => PaymentResponseHandler::CANCELLED], + ['resultCode' => PaymentResponseHandler::CANCELLED, 'hasGiftCard' => true] ]; } @@ -398,7 +399,7 @@ private static function handlePaymentsDetailsActionCancelledOrRefusedProvider(): * @throws NoSuchEntityException * @dataProvider handlePaymentsDetailsActionCancelledOrRefusedProvider */ - public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode) + public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode, $hasGiftCard = false) { $paymentsDetailsResponse = [ 'resultCode' => $resultCode, @@ -412,6 +413,16 @@ public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode) ] ]; + if ($hasGiftCard) { + $giftcardData = $this->testHasActiveGiftCardPayments(); + // Mock the dataHelper and service to simulate cancellation call + $this->dataHelperMock->expects($this->once())->method('initializeAdyenClient'); + $this->dataHelperMock->expects($this->once())->method('initializeOrdersApi'); + $this->adyenLoggerMock->expects($this->once())->method('error')->with( + 'Error canceling partial payments', + $this->anything() + ); + } $this->adyenLoggerMock->expects($this->atLeastOnce())->method('addAdyenResult'); $result = $this->paymentResponseHandler->handlePaymentsDetailsResponse( @@ -543,11 +554,6 @@ public function testOrderStatusUpdateWhenResponseIsValid() public function testHasActiveGiftCardPayments() { - - // Mock the addFieldToFilter method to return the collection itself for chaining - - - // Mock getSize to simulate an authorized gift card payment $this->paymentResponseMockForFactory->expects($this->any()) ->method('getSize') ->willReturn(1); // Simulate there is at least one record @@ -583,5 +589,6 @@ public function testHasActiveGiftCardPayments() $this->assertEquals([ ['merchant_reference' => '12345', 'result_code' => 'Authorised'] ], $result); + return $result; } } From f28a408fd0c31af7b779c0d5e31f38357fdf76ec Mon Sep 17 00:00:00 2001 From: khushboos Date: Mon, 21 Oct 2024 10:54:09 +0200 Subject: [PATCH 12/25] Updating unit test for asserting return from private methods --- Helper/PaymentResponseHandler.php | 2 +- .../Helper/PaymentResponseHandlerTest.php | 155 +++++++++++++----- 2 files changed, 111 insertions(+), 46 deletions(-) diff --git a/Helper/PaymentResponseHandler.php b/Helper/PaymentResponseHandler.php index 81963ab05..51ec1bbc4 100644 --- a/Helper/PaymentResponseHandler.php +++ b/Helper/PaymentResponseHandler.php @@ -409,7 +409,7 @@ private function isValidMerchantReference(array $paymentsDetailsResponse, OrderI } // Method to check for existing Gift Card payments - private function hasActiveGiftCardPayments($merchantReference) + public function hasActiveGiftCardPayments($merchantReference): array|string|null { $paymentResponseCollection = $this->paymentResponseCollectionFactory->create() ->addFieldToFilter('merchant_reference', $merchantReference) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index d66293cce..01a6b8eb2 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -387,8 +387,7 @@ private static function handlePaymentsDetailsActionCancelledOrRefusedProvider(): { return [ ['resultCode' => PaymentResponseHandler::REFUSED], - ['resultCode' => PaymentResponseHandler::CANCELLED], - ['resultCode' => PaymentResponseHandler::CANCELLED, 'hasGiftCard' => true] + ['resultCode' => PaymentResponseHandler::CANCELLED] ]; } @@ -399,7 +398,7 @@ private static function handlePaymentsDetailsActionCancelledOrRefusedProvider(): * @throws NoSuchEntityException * @dataProvider handlePaymentsDetailsActionCancelledOrRefusedProvider */ - public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode, $hasGiftCard = false) + public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode) { $paymentsDetailsResponse = [ 'resultCode' => $resultCode, @@ -412,17 +411,11 @@ public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode, $h 'actionData' => 'actionValue' ] ]; + $giftcardData = "{['merchant_reference' => '12345', 'result_code' => 'Authorised']"; + $this->paymentResponseHandler->method('hasActiveGiftCardPayments') + ->with('00123456') + ->willReturn($giftcardData); - if ($hasGiftCard) { - $giftcardData = $this->testHasActiveGiftCardPayments(); - // Mock the dataHelper and service to simulate cancellation call - $this->dataHelperMock->expects($this->once())->method('initializeAdyenClient'); - $this->dataHelperMock->expects($this->once())->method('initializeOrdersApi'); - $this->adyenLoggerMock->expects($this->once())->method('error')->with( - 'Error canceling partial payments', - $this->anything() - ); - } $this->adyenLoggerMock->expects($this->atLeastOnce())->method('addAdyenResult'); $result = $this->paymentResponseHandler->handlePaymentsDetailsResponse( @@ -552,43 +545,115 @@ public function testOrderStatusUpdateWhenResponseIsValid() $this->paymentResponseHandler->handlePaymentsDetailsResponse($paymentsDetailsResponse, $this->orderMock); } - public function testHasActiveGiftCardPayments() +// public function testHasActiveGiftCardPayments() +// { +// $this->paymentResponseMockForFactory->expects($this->any()) +// ->method('getSize') +// ->willReturn(1); // Simulate there is at least one record +// +// // Mock getData to return the desired array of data from the database +// $this->paymentResponseMockForFactory->expects($this->any()) +// ->method('getData') +// ->willReturn([ +// ['merchant_reference' => '12345', 'result_code' => 'Authorised'] +// ]); +// +// $this->paymentResponseCollectionFactoryMock->expects($this->any()) +// ->method('create') +// ->willReturn($this->paymentResponseMockForFactory); +// +// // Create an instance of the class that has the private method +// $class = new \ReflectionClass(PaymentResponseHandler::class); +// $instance = $class->newInstanceWithoutConstructor(); +// +// // Inject the mocked factory into the instance if necessary +// $property = $class->getProperty('paymentResponseCollectionFactory'); +// $property->setAccessible(true); +// $property->setValue($instance, $this->paymentResponseCollectionFactoryMock); +// +// // Use Reflection to access the private method +// $method = $class->getMethod('hasActiveGiftCardPayments'); +// $method->setAccessible(true); +// +// // Call the private method with the required parameters +// $result = $method->invoke($instance, '12345'); +// +// // Assert the expected result +// $this->assertEquals([ +// ['merchant_reference' => '12345', 'result_code' => 'Authorised'] +// ], $result); +// return $result; +// } + + public function testCancelledScenarioWithActiveGiftCardPayments() { - $this->paymentResponseMockForFactory->expects($this->any()) - ->method('getSize') - ->willReturn(1); // Simulate there is at least one record - - // Mock getData to return the desired array of data from the database - $this->paymentResponseMockForFactory->expects($this->any()) - ->method('getData') - ->willReturn([ - ['merchant_reference' => '12345', 'result_code' => 'Authorised'] - ]); + $merchantReference = 'test_merchant_reference'; + $storeId = 1; - $this->paymentResponseCollectionFactoryMock->expects($this->any()) - ->method('create') - ->willReturn($this->paymentResponseMockForFactory); - - // Create an instance of the class that has the private method - $class = new \ReflectionClass(PaymentResponseHandler::class); - $instance = $class->newInstanceWithoutConstructor(); + // Mock the order object + $orderMock = $this->createMock(\Magento\Sales\Model\Order::class); + $orderMock->expects($this->once())->method('getStoreId')->willReturn($storeId); + $orderMock->expects($this->once())->method('canCancel')->willReturn(true); // Order can be canceled + $orderMock->expects($this->once())->method('setActionFlag')->with(\Magento\Sales\Model\Order::ACTION_FLAG_CANCEL, true); + + // Mock the payment response collection to simulate existing gift card payments + $giftCardDetails = [ + [ + 'response' => json_encode([ + 'order' => [ + 'orderData' => 'test_order_data', + 'pspReference' => 'test_psp_reference' + ] + ]) + ] + ]; - // Inject the mocked factory into the instance if necessary - $property = $class->getProperty('paymentResponseCollectionFactory'); - $property->setAccessible(true); - $property->setValue($instance, $this->paymentResponseCollectionFactoryMock); + $giftcardData = $this->paymentResponseHandler->hasActiveGiftCardPayments(''); + if(empty($giftcardData)) + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Invalid giftcard response data'); + } - // Use Reflection to access the private method - $method = $class->getMethod('hasActiveGiftCardPayments'); - $method->setAccessible(true); + // Mock the Adyen client and Orders API + $clientMock = $this->createMock(\Adyen\Client::class); + $ordersApiMock = $this->createMock(\Adyen\Service\Orders::class); + + $this->dataHelperMock->expects($this->once()) + ->method('initializeAdyenClient') + ->with($storeId) + ->willReturn($clientMock); + + $this->dataHelperMock->expects($this->once()) + ->method('initializeOrdersApi') + ->with($clientMock) + ->willReturn($ordersApiMock); + + // Mock the cancelOrder API call and its response + $cancelOrderRequestMock = $this->createMock(\Adyen\Service\ResourceModel\Order\Cancel::class); + $ordersApiMock->expects($this->once()) + ->method('cancelOrder') + ->with($this->isInstanceOf(\Adyen\Service\ResourceModel\Order\CancelOrderRequest::class)) + ->willReturn($cancelOrderRequestMock); + + $cancelOrderRequestMock->expects($this->once()) + ->method('toArray') + ->willReturn(['resultCode' => 'Cancelled']); + + // Mock the dataHelper's cancelOrder method + $this->dataHelperMock->expects($this->once()) + ->method('cancelOrder') + ->with($orderMock); + + // Run the actual method under test + $paymentsDetailsResponse = [ + 'merchantReference' => $merchantReference, + ]; - // Call the private method with the required parameters - $result = $method->invoke($instance, '12345'); + $result = $this->paymentResponseHandler->handlePaymentsDetailsResponse($paymentsDetailsResponse, $orderMock); - // Assert the expected result - $this->assertEquals([ - ['merchant_reference' => '12345', 'result_code' => 'Authorised'] - ], $result); - return $result; + // Assert the result is false after canceling + $this->assertFalse($result); } + } From 7214dd2428b588bb1ff61e3c779572e64255ae2e Mon Sep 17 00:00:00 2001 From: khushboos Date: Tue, 22 Oct 2024 16:51:26 +0200 Subject: [PATCH 13/25] Updating unit test for asserting return from private methods --- Helper/PaymentResponseHandler.php | 2 +- .../Helper/PaymentResponseHandlerTest.php | 146 ++++-------------- 2 files changed, 29 insertions(+), 119 deletions(-) diff --git a/Helper/PaymentResponseHandler.php b/Helper/PaymentResponseHandler.php index 51ec1bbc4..e804e167b 100644 --- a/Helper/PaymentResponseHandler.php +++ b/Helper/PaymentResponseHandler.php @@ -409,7 +409,7 @@ private function isValidMerchantReference(array $paymentsDetailsResponse, OrderI } // Method to check for existing Gift Card payments - public function hasActiveGiftCardPayments($merchantReference): array|string|null + private function hasActiveGiftCardPayments($merchantReference): array|string|null { $paymentResponseCollection = $this->paymentResponseCollectionFactory->create() ->addFieldToFilter('merchant_reference', $merchantReference) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 01a6b8eb2..234249303 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -68,8 +68,7 @@ protected function setUp(): void $this->paymentResponseMockForFactory = $this->createMock(Collection::class); // Mock PaymentResponseCollectionFactory to return the mocked collection - $this->paymentResponseCollectionFactoryMock = $this->createGeneratedMock(CollectionFactory::class, ['create']); - $this->paymentResponseCollectionFactoryMock->method('create')->willReturn($this->paymentResponseMockForFactory); + $this->paymentResponseCollectionFactoryMock = $this->createMock(CollectionFactory::class); $this->paymentResponseMockForFactory->expects($this->any()) ->method('addFieldToFilter') ->willReturn($this->paymentResponseMockForFactory); @@ -411,10 +410,33 @@ public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode) 'actionData' => 'actionValue' ] ]; - $giftcardData = "{['merchant_reference' => '12345', 'result_code' => 'Authorised']"; - $this->paymentResponseHandler->method('hasActiveGiftCardPayments') - ->with('00123456') - ->willReturn($giftcardData); + $this->paymentResponseMockForFactory->expects($this->any()) + ->method('getSize') + ->willReturn(1); // Simulate there is at least one record + + // Mock getData to return the desired array of data from the database + $this->paymentResponseMockForFactory->expects($this->any()) + ->method('getData') + ->willReturn([ + ['merchant_reference' => '12345', 'result_code' => 'Authorised'] + ]); + + $this->paymentResponseCollectionFactoryMock->expects($this->any()) + ->method('create') + ->willReturn($this->paymentResponseMockForFactory); + + // Create an instance of the class that has the private method + $class = new \ReflectionClass(PaymentResponseHandler::class); + $instance = $class->newInstanceWithoutConstructor(); + + // Inject the mocked factory into the instance if necessary + $property = $class->getProperty('paymentResponseCollectionFactory'); + $property->setAccessible(true); + $property->setValue($instance, $this->paymentResponseCollectionFactoryMock); + + // Use Reflection to access the private method + $method = $class->getMethod('hasActiveGiftCardPayments'); + $method->setAccessible(true); $this->adyenLoggerMock->expects($this->atLeastOnce())->method('addAdyenResult'); @@ -544,116 +566,4 @@ public function testOrderStatusUpdateWhenResponseIsValid() $this->paymentResponseHandler->handlePaymentsDetailsResponse($paymentsDetailsResponse, $this->orderMock); } - -// public function testHasActiveGiftCardPayments() -// { -// $this->paymentResponseMockForFactory->expects($this->any()) -// ->method('getSize') -// ->willReturn(1); // Simulate there is at least one record -// -// // Mock getData to return the desired array of data from the database -// $this->paymentResponseMockForFactory->expects($this->any()) -// ->method('getData') -// ->willReturn([ -// ['merchant_reference' => '12345', 'result_code' => 'Authorised'] -// ]); -// -// $this->paymentResponseCollectionFactoryMock->expects($this->any()) -// ->method('create') -// ->willReturn($this->paymentResponseMockForFactory); -// -// // Create an instance of the class that has the private method -// $class = new \ReflectionClass(PaymentResponseHandler::class); -// $instance = $class->newInstanceWithoutConstructor(); -// -// // Inject the mocked factory into the instance if necessary -// $property = $class->getProperty('paymentResponseCollectionFactory'); -// $property->setAccessible(true); -// $property->setValue($instance, $this->paymentResponseCollectionFactoryMock); -// -// // Use Reflection to access the private method -// $method = $class->getMethod('hasActiveGiftCardPayments'); -// $method->setAccessible(true); -// -// // Call the private method with the required parameters -// $result = $method->invoke($instance, '12345'); -// -// // Assert the expected result -// $this->assertEquals([ -// ['merchant_reference' => '12345', 'result_code' => 'Authorised'] -// ], $result); -// return $result; -// } - - public function testCancelledScenarioWithActiveGiftCardPayments() - { - $merchantReference = 'test_merchant_reference'; - $storeId = 1; - - // Mock the order object - $orderMock = $this->createMock(\Magento\Sales\Model\Order::class); - $orderMock->expects($this->once())->method('getStoreId')->willReturn($storeId); - $orderMock->expects($this->once())->method('canCancel')->willReturn(true); // Order can be canceled - $orderMock->expects($this->once())->method('setActionFlag')->with(\Magento\Sales\Model\Order::ACTION_FLAG_CANCEL, true); - - // Mock the payment response collection to simulate existing gift card payments - $giftCardDetails = [ - [ - 'response' => json_encode([ - 'order' => [ - 'orderData' => 'test_order_data', - 'pspReference' => 'test_psp_reference' - ] - ]) - ] - ]; - - $giftcardData = $this->paymentResponseHandler->hasActiveGiftCardPayments(''); - if(empty($giftcardData)) - { - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Invalid giftcard response data'); - } - - // Mock the Adyen client and Orders API - $clientMock = $this->createMock(\Adyen\Client::class); - $ordersApiMock = $this->createMock(\Adyen\Service\Orders::class); - - $this->dataHelperMock->expects($this->once()) - ->method('initializeAdyenClient') - ->with($storeId) - ->willReturn($clientMock); - - $this->dataHelperMock->expects($this->once()) - ->method('initializeOrdersApi') - ->with($clientMock) - ->willReturn($ordersApiMock); - - // Mock the cancelOrder API call and its response - $cancelOrderRequestMock = $this->createMock(\Adyen\Service\ResourceModel\Order\Cancel::class); - $ordersApiMock->expects($this->once()) - ->method('cancelOrder') - ->with($this->isInstanceOf(\Adyen\Service\ResourceModel\Order\CancelOrderRequest::class)) - ->willReturn($cancelOrderRequestMock); - - $cancelOrderRequestMock->expects($this->once()) - ->method('toArray') - ->willReturn(['resultCode' => 'Cancelled']); - - // Mock the dataHelper's cancelOrder method - $this->dataHelperMock->expects($this->once()) - ->method('cancelOrder') - ->with($orderMock); - - // Run the actual method under test - $paymentsDetailsResponse = [ - 'merchantReference' => $merchantReference, - ]; - - $result = $this->paymentResponseHandler->handlePaymentsDetailsResponse($paymentsDetailsResponse, $orderMock); - - // Assert the result is false after canceling - $this->assertFalse($result); - } - } From 416e397daab4a61e9a1c05486a701070c409cd7e Mon Sep 17 00:00:00 2001 From: khushboos Date: Tue, 22 Oct 2024 16:57:08 +0200 Subject: [PATCH 14/25] Updating unit test for asserting return from private methods --- Test/Unit/Helper/PaymentResponseHandlerTest.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 234249303..0ed8923c8 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -66,12 +66,9 @@ protected function setUp(): void $this->configHelperMock = $this->createMock(Config::class); $this->paymentResponseMockForFactory = $this->createMock(Collection::class); - // Mock PaymentResponseCollectionFactory to return the mocked collection $this->paymentResponseCollectionFactoryMock = $this->createMock(CollectionFactory::class); - $this->paymentResponseMockForFactory->expects($this->any()) - ->method('addFieldToFilter') - ->willReturn($this->paymentResponseMockForFactory); + $orderHistory = $this->createMock(History::class); $orderHistory->method('setStatus')->willReturnSelf(); $orderHistory->method('setComment')->willReturnSelf(); @@ -410,6 +407,11 @@ public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode) 'actionData' => 'actionValue' ] ]; + + $this->paymentResponseMockForFactory->expects($this->any()) + ->method('addFieldToFilter') + ->willReturn($this->paymentResponseMockForFactory); + $this->paymentResponseMockForFactory->expects($this->any()) ->method('getSize') ->willReturn(1); // Simulate there is at least one record From f5b530d79b395b80ca1fed2618a97ae8c784098f Mon Sep 17 00:00:00 2001 From: khushboos Date: Wed, 23 Oct 2024 09:27:46 +0200 Subject: [PATCH 15/25] Updating unit test for asserting return from private methods --- Test/Unit/Helper/PaymentResponseHandlerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 0ed8923c8..169617209 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -67,7 +67,7 @@ protected function setUp(): void $this->paymentResponseMockForFactory = $this->createMock(Collection::class); - $this->paymentResponseCollectionFactoryMock = $this->createMock(CollectionFactory::class); + $this->paymentResponseCollectionFactoryMock = $this->createGeneratedMock(CollectionFactory::class, ['create']); $orderHistory = $this->createMock(History::class); $orderHistory->method('setStatus')->willReturnSelf(); From 0b99a026a4f5e856677878cdf97d18819ba95084 Mon Sep 17 00:00:00 2001 From: khushboos Date: Wed, 23 Oct 2024 09:55:59 +0200 Subject: [PATCH 16/25] Updating unit test for asserting return from private methods --- Test/Unit/Helper/PaymentResponseHandlerTest.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 169617209..3cf9dcf85 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -420,7 +420,20 @@ public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode) $this->paymentResponseMockForFactory->expects($this->any()) ->method('getData') ->willReturn([ - ['merchant_reference' => '12345', 'result_code' => 'Authorised'] + [ + 'merchant_reference' => '12345', + 'result_code' => 'Authorised', + 'response' => '{ + "additionalData":{"paymentMethod":"svs","merchantReference":"123","acquirerCode":"Test"}, + "amount":{"currency":"EUR","value":5000}, + "merchantReference":"123", + "order":{"amount":{"currency":"EUR","value":17800},"expiresAt":"2024-10-10T13:11:37Z", + "pspReference":"XYZ654", + "reference":"123", + "remainingAmount":{"currency":"EUR","value":12800}}, + "paymentMethod":{"brand":"svs","type":"giftcard"}, + "pspReference":"ABC123","resultCode":"Authorised"}' + ] ]); $this->paymentResponseCollectionFactoryMock->expects($this->any()) From b522bf919b5d0127699fcd6a583439de1bb14b74 Mon Sep 17 00:00:00 2001 From: khushboos Date: Wed, 23 Oct 2024 10:12:13 +0200 Subject: [PATCH 17/25] Adding more assertions --- Test/Unit/Helper/PaymentResponseHandlerTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 3cf9dcf85..bcfa123fd 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -452,6 +452,12 @@ public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode) // Use Reflection to access the private method $method = $class->getMethod('hasActiveGiftCardPayments'); $method->setAccessible(true); + $merchantAccount = 'mock_merchant_account'; + $storeId = 1; + $this->configHelperMock + ->method('getAdyenAbstractConfigData') + ->with('merchant_account', $storeId) + ->willReturn($merchantAccount); $this->adyenLoggerMock->expects($this->atLeastOnce())->method('addAdyenResult'); From e2a23a96ab97af85ccfaa0676f609fd6d44af71d Mon Sep 17 00:00:00 2001 From: khushboos Date: Wed, 23 Oct 2024 11:01:45 +0200 Subject: [PATCH 18/25] Adding more assertions --- .../Helper/PaymentResponseHandlerTest.php | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index bcfa123fd..71ac77bb8 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -428,6 +428,7 @@ public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode) "amount":{"currency":"EUR","value":5000}, "merchantReference":"123", "order":{"amount":{"currency":"EUR","value":17800},"expiresAt":"2024-10-10T13:11:37Z", + "orderData":"orderData....", "pspReference":"XYZ654", "reference":"123", "remainingAmount":{"currency":"EUR","value":12800}}, @@ -440,6 +441,14 @@ public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode) ->method('create') ->willReturn($this->paymentResponseMockForFactory); + $merchantAccount = 'mock_merchant_account'; + $storeId = 1; + $this->orderMock->expects($this->once())->method('getStoreId')->willReturn($storeId); + $this->configHelperMock->expects($this->any()) + ->method('getAdyenAbstractConfigData') + ->with('merchant_account', $storeId) + ->willReturn($merchantAccount); + // Create an instance of the class that has the private method $class = new \ReflectionClass(PaymentResponseHandler::class); $instance = $class->newInstanceWithoutConstructor(); @@ -452,12 +461,11 @@ public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode) // Use Reflection to access the private method $method = $class->getMethod('hasActiveGiftCardPayments'); $method->setAccessible(true); - $merchantAccount = 'mock_merchant_account'; - $storeId = 1; - $this->configHelperMock - ->method('getAdyenAbstractConfigData') - ->with('merchant_account', $storeId) - ->willReturn($merchantAccount); + + // Mock order cancellation + $this->orderMock->expects($this->any()) + ->method('canCancel') + ->willReturn(true); $this->adyenLoggerMock->expects($this->atLeastOnce())->method('addAdyenResult'); From 258f3422729280e877d6857fcf1baf2e7f01e438 Mon Sep 17 00:00:00 2001 From: khushboos Date: Wed, 23 Oct 2024 15:58:36 +0200 Subject: [PATCH 19/25] Updating logic of canceling the already authorised the giftcards orders --- Helper/PaymentResponseHandler.php | 112 +++++++++++++++--------------- 1 file changed, 55 insertions(+), 57 deletions(-) diff --git a/Helper/PaymentResponseHandler.php b/Helper/PaymentResponseHandler.php index e804e167b..7529379a5 100644 --- a/Helper/PaymentResponseHandler.php +++ b/Helper/PaymentResponseHandler.php @@ -26,6 +26,7 @@ use Magento\Sales\Model\Order as OrderModel; use Adyen\Payment\Helper\Data as Data; use Magento\Framework\Mail\Exception\InvalidArgumentException; +use Adyen\Client; class PaymentResponseHandler { @@ -290,61 +291,10 @@ public function handlePaymentsDetailsResponse( break; case self::REFUSED: case self::CANCELLED: - $getGiftcardDetails = $this->hasActiveGiftCardPayments( - $paymentsDetailsResponse['merchantReference'] + $this->hasActiveGiftCardPayments( + $paymentsDetailsResponse['merchantReference'], $order ); - if (!empty($getGiftcardDetails)) { - //Cancel the Authorised Payments - $storeId = $order->getStoreId(); - $client = $this->dataHelper->initializeAdyenClient($storeId); - $service = $this->dataHelper->initializeOrdersApi($client); - foreach ($getGiftcardDetails as $giftcardData) { - try { - // Decode JSON response and validate it - $response = json_decode($giftcardData['response'], true); - if (json_last_error() !== JSON_ERROR_NONE || !isset($response['order'])) { - throw new InvalidArgumentException('Invalid giftcard response data'); - } - - // Extract order data and PSPRef - $orderData = $response['order']['orderData'] ?? null; - $pspReference = $response['order']['pspReference'] ?? null; - - if (!$orderData || !$pspReference) { - throw new InvalidArgumentException('Missing orderData or pspReference in the response'); - } - - // Prepare cancel request - $merchantAccount = $this->configHelper->getAdyenAbstractConfigData("merchant_account", $storeId); - $cancelRequest = [ - 'order' => [ - 'pspReference' => $pspReference, - 'orderData' => $orderData, - ], - 'merchantAccount' => $merchantAccount, - ]; - - // Call the cancel service - $cancelResponse = $service->cancelOrder(new CancelOrderRequest($cancelRequest)); - $response = $cancelResponse->toArray(); - - if (is_null($response['resultCode'])) { - // In case the result is unknown we log the request and don't update the history - $this->adyenLogger->error( - "Unexpected result query parameter for cancel order request. Response: " . json_encode($response) - ); - - return false; - } - } catch (\Exception $e) { - // Log the error with relevant information for debugging - $this->adyenLogger->error('Error canceling partial payments', [ - 'exception' => $e->getMessage(), - 'giftcardData' => $giftcardData, - ]); - } - } - } + // Cancel order in case result is refused if (null !== $order) { // Check if the current state allows for changing to new for cancellation @@ -409,15 +359,63 @@ private function isValidMerchantReference(array $paymentsDetailsResponse, OrderI } // Method to check for existing Gift Card payments - private function hasActiveGiftCardPayments($merchantReference): array|string|null + private function hasActiveGiftCardPayments($merchantReference, $order) { $paymentResponseCollection = $this->paymentResponseCollectionFactory->create() ->addFieldToFilter('merchant_reference', $merchantReference) ->addFieldToFilter('result_code', 'Authorised'); if ($paymentResponseCollection->getSize() > 0) { - return $paymentResponseCollection->getData(); + $getGiftcardDetails = $paymentResponseCollection->getData(); + + //Cancel the Authorised Payments + $storeId = $order->getStoreId(); + $client = $this->dataHelper->initializeAdyenClient($storeId); + $service = $this->dataHelper->initializeOrdersApi($client); + foreach ($getGiftcardDetails as $giftcardData) { + try { + // Decode JSON response and validate it + $response = json_decode($giftcardData['response'], true); + if (json_last_error() !== JSON_ERROR_NONE || !isset($response['order'])) { + throw new InvalidArgumentException('Invalid giftcard response data'); + } + + // Extract order data and PSPRef + $orderData = $response['order']['orderData'] ?? null; + $pspReference = $response['order']['pspReference'] ?? null; + + if (!$orderData || !$pspReference) { + throw new InvalidArgumentException('Missing orderData or pspReference in the response'); + } + + // Prepare cancel request + $merchantAccount = $this->configHelper->getAdyenAbstractConfigData("merchant_account", $storeId); + $cancelRequest = [ + 'order' => [ + 'pspReference' => $pspReference, + 'orderData' => $orderData, + ], + 'merchantAccount' => $merchantAccount, + ]; + $this->dataHelper->logRequest($cancelRequest, Client::API_CHECKOUT_VERSION, '/orders/cancel'); + // Call the cancel service + $cancelResponse = $service->cancelOrder(new CancelOrderRequest($cancelRequest)); + $response = $cancelResponse->toArray(); + $this->dataHelper->logResponse($response); + if (is_null($response['resultCode'])) { + // In case the result is unknown we log the request and don't update the history + $this->adyenLogger->error( + "Unexpected result query parameter for cancel order request. Response: " . json_encode($response) + ); + } + } catch (\Exception $e) { + // Log the error with relevant information for debugging + $this->adyenLogger->error('Error canceling partial payments', [ + 'exception' => $e->getMessage(), + 'giftcardData' => $giftcardData, + ]); + } + } } - return ''; } } From fb4e7eaf24dd059eace96d2cb9053ed060dbd5a4 Mon Sep 17 00:00:00 2001 From: Khushboo Date: Mon, 28 Oct 2024 14:33:09 +0100 Subject: [PATCH 20/25] Update Test/Unit/Helper/PaymentResponseHandlerTest.php Co-authored-by: Peter Ojo --- Test/Unit/Helper/PaymentResponseHandlerTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 71ac77bb8..8843b4844 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -433,7 +433,9 @@ public function testHandlePaymentsDetailsResponseCancelOrRefused($resultCode) "reference":"123", "remainingAmount":{"currency":"EUR","value":12800}}, "paymentMethod":{"brand":"svs","type":"giftcard"}, - "pspReference":"ABC123","resultCode":"Authorised"}' + "pspReference":"ABC123", + "resultCode":"Authorised" + }' ] ]); From 75172c5441ea1811ad491067160ce2ab221ec620 Mon Sep 17 00:00:00 2001 From: Khushboo Date: Mon, 28 Oct 2024 15:42:45 +0100 Subject: [PATCH 21/25] Update .github/workflows/main.yml Co-authored-by: Peter Ojo --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index de79e4ac3..871fb21f8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,7 +24,7 @@ jobs: uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} - tools: composer:2 + tools: composer:v2 - name: Test plugin installation run: | From 3eb591ec0e03853e27238b844c5a3873c9209344 Mon Sep 17 00:00:00 2001 From: khushboos Date: Tue, 5 Nov 2024 15:09:56 +0100 Subject: [PATCH 22/25] Updating unit test for Index.php with more case scenarios --- Helper/PaymentResponseHandler.php | 103 ++++++++++++++++-------------- 1 file changed, 56 insertions(+), 47 deletions(-) diff --git a/Helper/PaymentResponseHandler.php b/Helper/PaymentResponseHandler.php index 7529379a5..24e6374e8 100644 --- a/Helper/PaymentResponseHandler.php +++ b/Helper/PaymentResponseHandler.php @@ -291,10 +291,15 @@ public function handlePaymentsDetailsResponse( break; case self::REFUSED: case self::CANCELLED: - $this->hasActiveGiftCardPayments( - $paymentsDetailsResponse['merchantReference'], $order + $activeGiftCards = $this->hasActiveGiftCardPayments( + $paymentsDetailsResponse['merchantReference'] ); + if(null !== $activeGiftCards) + { + $this->cancelGiftCardOrders($activeGiftCards,$order); + } + // Cancel order in case result is refused if (null !== $order) { // Check if the current state allows for changing to new for cancellation @@ -359,62 +364,66 @@ private function isValidMerchantReference(array $paymentsDetailsResponse, OrderI } // Method to check for existing Gift Card payments - private function hasActiveGiftCardPayments($merchantReference, $order) + private function hasActiveGiftCardPayments($merchantReference) { $paymentResponseCollection = $this->paymentResponseCollectionFactory->create() ->addFieldToFilter('merchant_reference', $merchantReference) ->addFieldToFilter('result_code', 'Authorised'); if ($paymentResponseCollection->getSize() > 0) { - $getGiftcardDetails = $paymentResponseCollection->getData(); + return $paymentResponseCollection->getData(); + } + return null; + } - //Cancel the Authorised Payments - $storeId = $order->getStoreId(); - $client = $this->dataHelper->initializeAdyenClient($storeId); - $service = $this->dataHelper->initializeOrdersApi($client); - foreach ($getGiftcardDetails as $giftcardData) { - try { - // Decode JSON response and validate it - $response = json_decode($giftcardData['response'], true); - if (json_last_error() !== JSON_ERROR_NONE || !isset($response['order'])) { - throw new InvalidArgumentException('Invalid giftcard response data'); - } + private function cancelGiftCardOrders($activeGiftCards, $order) + { + //Cancel the Authorised GC Payments + $storeId = $order->getStoreId(); + $client = $this->dataHelper->initializeAdyenClient($storeId); + $service = $this->dataHelper->initializeOrdersApi($client); + foreach ($activeGiftCards as $giftcardData) { + try { + // Decode JSON response and validate it + $response = json_decode($giftcardData['response'], true); + if (json_last_error() !== JSON_ERROR_NONE || !isset($response['order'])) { + throw new InvalidArgumentException('Invalid giftcard response data'); + } - // Extract order data and PSPRef - $orderData = $response['order']['orderData'] ?? null; - $pspReference = $response['order']['pspReference'] ?? null; + // Extract order data and PSPRef + $orderData = $response['order']['orderData'] ?? null; + $pspReference = $response['order']['pspReference'] ?? null; - if (!$orderData || !$pspReference) { - throw new InvalidArgumentException('Missing orderData or pspReference in the response'); - } + if (!$orderData || !$pspReference) { + throw new InvalidArgumentException('Missing orderData or pspReference in the response'); + } - // Prepare cancel request - $merchantAccount = $this->configHelper->getAdyenAbstractConfigData("merchant_account", $storeId); - $cancelRequest = [ - 'order' => [ - 'pspReference' => $pspReference, - 'orderData' => $orderData, - ], - 'merchantAccount' => $merchantAccount, - ]; - $this->dataHelper->logRequest($cancelRequest, Client::API_CHECKOUT_VERSION, '/orders/cancel'); - // Call the cancel service - $cancelResponse = $service->cancelOrder(new CancelOrderRequest($cancelRequest)); - $response = $cancelResponse->toArray(); - $this->dataHelper->logResponse($response); - if (is_null($response['resultCode'])) { - // In case the result is unknown we log the request and don't update the history - $this->adyenLogger->error( - "Unexpected result query parameter for cancel order request. Response: " . json_encode($response) - ); - } - } catch (\Exception $e) { - // Log the error with relevant information for debugging - $this->adyenLogger->error('Error canceling partial payments', [ - 'exception' => $e->getMessage(), - 'giftcardData' => $giftcardData, - ]); + // Prepare cancel request + $merchantAccount = $this->configHelper->getAdyenAbstractConfigData("merchant_account", $storeId); + $cancelRequest = [ + 'order' => [ + 'pspReference' => $pspReference, + 'orderData' => $orderData, + ], + 'merchantAccount' => $merchantAccount, + ]; + $this->dataHelper->logRequest($cancelRequest, Client::API_CHECKOUT_VERSION, '/orders/cancel'); + // Call the cancel service + $cancelResponse = $service->cancelOrder(new CancelOrderRequest($cancelRequest)); + $response = $cancelResponse->toArray(); + $this->dataHelper->logResponse($response); + if (is_null($response['resultCode'])) { + // In case the result is unknown we log the request and don't update the history + $this->adyenLogger->error( + "Unexpected result query parameter for cancel order request. Response: " . json_encode($response) + ); } + } catch (\Exception $e) { + // Log the error with relevant information for debugging + $this->adyenLogger->error('Error canceling partial payments', [ + 'exception' => $e->getMessage(), + 'giftcardData' => $giftcardData, + ]); } } } From bfbbc4f2338b3e6355d97c08a8459e66c2099fcb Mon Sep 17 00:00:00 2001 From: Khushboo Date: Wed, 6 Nov 2024 11:48:22 +0100 Subject: [PATCH 23/25] Update Helper/PaymentResponseHandler.php Co-authored-by: Peter Ojo --- Helper/PaymentResponseHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Helper/PaymentResponseHandler.php b/Helper/PaymentResponseHandler.php index 24e6374e8..eae4a5fa2 100644 --- a/Helper/PaymentResponseHandler.php +++ b/Helper/PaymentResponseHandler.php @@ -12,7 +12,7 @@ namespace Adyen\Payment\Helper; use Adyen\Model\Checkout\CancelOrderRequest; -use Adyen\Payment\Helper\Config as Config; +use Adyen\Payment\Helper\Config; use Adyen\Payment\Logger\AdyenLogger; use Adyen\Payment\Model\ResourceModel\PaymentResponse\CollectionFactory as PaymentResponseCollectionFactory; use Exception; From 9d1eeefb837ce0f3b76ce578bea0e030dd6b0dc3 Mon Sep 17 00:00:00 2001 From: Khushboo Date: Wed, 6 Nov 2024 11:48:31 +0100 Subject: [PATCH 24/25] Update Helper/PaymentResponseHandler.php Co-authored-by: Peter Ojo --- Helper/PaymentResponseHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Helper/PaymentResponseHandler.php b/Helper/PaymentResponseHandler.php index eae4a5fa2..ca1df9983 100644 --- a/Helper/PaymentResponseHandler.php +++ b/Helper/PaymentResponseHandler.php @@ -24,7 +24,7 @@ use Magento\Sales\Model\OrderRepository; use Magento\Sales\Model\ResourceModel\Order; use Magento\Sales\Model\Order as OrderModel; -use Adyen\Payment\Helper\Data as Data; +use Adyen\Payment\Helper\Data; use Magento\Framework\Mail\Exception\InvalidArgumentException; use Adyen\Client; From ecd5bd966ffd446b0a767ddc01a16904f70f0fe6 Mon Sep 17 00:00:00 2001 From: Khushboo Date: Wed, 6 Nov 2024 11:48:43 +0100 Subject: [PATCH 25/25] Update Test/Unit/Helper/PaymentResponseHandlerTest.php Co-authored-by: Peter Ojo --- Test/Unit/Helper/PaymentResponseHandlerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Test/Unit/Helper/PaymentResponseHandlerTest.php b/Test/Unit/Helper/PaymentResponseHandlerTest.php index 8843b4844..0bff0bbf2 100644 --- a/Test/Unit/Helper/PaymentResponseHandlerTest.php +++ b/Test/Unit/Helper/PaymentResponseHandlerTest.php @@ -30,7 +30,7 @@ use Adyen\Payment\Helper\StateData; use Adyen\Payment\Model\ResourceModel\PaymentResponse\Collection; use Adyen\Payment\Model\ResourceModel\PaymentResponse\CollectionFactory; -use Adyen\Payment\Helper\Config as Config; +use Adyen\Payment\Helper\Config; use ReflectionClass; class PaymentResponseHandlerTest extends AbstractAdyenTestCase