diff --git a/Helper/Webhook/OfferClosedWebhookHandler.php b/Helper/Webhook/OfferClosedWebhookHandler.php index 9695736d72..3e135009d9 100644 --- a/Helper/Webhook/OfferClosedWebhookHandler.php +++ b/Helper/Webhook/OfferClosedWebhookHandler.php @@ -12,6 +12,7 @@ namespace Adyen\Payment\Helper\Webhook; +use Adyen\AdyenException; use Adyen\Payment\Helper\Config; use Adyen\Payment\Helper\Order; use Adyen\Payment\Helper\PaymentMethods; @@ -55,6 +56,7 @@ public function __construct( /** * @throws LocalizedException + * @throws AdyenException */ public function handleWebhook(MagentoOrder $order, Notification $notification, string $transitionState): MagentoOrder { @@ -88,12 +90,14 @@ public function handleWebhook(MagentoOrder $order, Notification $notification, s ); if (!$identicalPaymentMethods) { + $paymentMethodInstance = $order->getPayment()->getMethodInstance(); $this->adyenLogger->addAdyenNotification(sprintf( 'Payment method of notification %s (%s) does not match the payment method (%s) of order %s', $notification->getId(), $notification->getPaymentMethod(), $order->getIncrementId(), - $order->getPayment()->getCcType() + $this->paymentMethodsHelper->getAlternativePaymentMethodTxVariant( + $paymentMethodInstance) ), [ 'pspReference' => $notification->getPspreference(), diff --git a/Observer/AdyenPaymentMethodDataAssignObserver.php b/Observer/AdyenPaymentMethodDataAssignObserver.php index efe803a0fc..dec4a5cae2 100644 --- a/Observer/AdyenPaymentMethodDataAssignObserver.php +++ b/Observer/AdyenPaymentMethodDataAssignObserver.php @@ -119,10 +119,5 @@ public function execute(Observer $observer) $paymentInfo->setAdditionalInformation($key, $data); } - // Set ccType. If payment method is tokenizable, update additional information - if (!empty($additionalData[self::BRAND_CODE])) { - $paymentMethod = $additionalData[self::BRAND_CODE]; - $paymentInfo->setCcType($paymentMethod); - } } } diff --git a/Test/Unit/Helper/Webhook/OfferClosedWebhookHandlerTest.php b/Test/Unit/Helper/Webhook/OfferClosedWebhookHandlerTest.php index 5aa46668c0..bff5cc75ec 100644 --- a/Test/Unit/Helper/Webhook/OfferClosedWebhookHandlerTest.php +++ b/Test/Unit/Helper/Webhook/OfferClosedWebhookHandlerTest.php @@ -7,6 +7,7 @@ use Adyen\Payment\Helper\Order; use Adyen\Payment\Helper\PaymentMethods; use Adyen\Payment\Logger\AdyenLogger; +use Adyen\Payment\Model\Method\Adapter; use Adyen\Payment\Model\Notification; use Adyen\Payment\Model\ResourceModel\Order\Payment as OrderPaymentResourceModel; use Magento\Sales\Model\Order as MagentoOrder; @@ -67,21 +68,28 @@ public function testHandleWebhookThrowsExceptionForInvalidPaymentMethod() { // Create a sample MagentoOrder and Notification $order = $this->createMock(MagentoOrder::class); - $order->method('getPayment')->willReturn($this->createPartialMock(Payment::class, ['getMethod'])); + $paymentMethodInstanceMock = $this->createMock(Adapter::class); + $order->method('getPayment')->willReturn($this->createPartialMock(Payment::class, ['getMethod','getMethodInstance'])); $order->getPayment()->method('getMethod')->willReturn('adyen_cc'); + $order->getPayment()->method('getMethodInstance')->willReturn($paymentMethodInstanceMock); $notification = $this->createMock(Notification::class); - // Mock payment method mismatch - $this->paymentMethodsHelper->method('compareOrderAndWebhookPaymentMethods')->with($order,$notification)->willReturn(false); + // Mock payment method comparison behavior + $this->paymentMethodsHelper->method('compareOrderAndWebhookPaymentMethods') + ->with($order, $notification) + ->willReturn(false); // Create an instance of the OfferClosedWebhookHandler - $webhookHandler = $this->createOfferClosedWebhookHandler($this->paymentMethodsHelper,null,null,null,null); + $webhookHandler = $this->createOfferClosedWebhookHandler($this->paymentMethodsHelper, null, null, null, null); // Call the handleWebhook method to trigger the exception $result = $webhookHandler->handleWebhook($order, $notification, 'PAYMENT_REVIEW'); + + // Verify the expected result $this->assertEquals($order, $result); } + public function testHandleWebhookReturnsOrderWhenCapturedPaymentsExist() { // Create a sample MagentoOrder and Notification diff --git a/Test/Unit/Observer/AdyenPaymentMethodDataAssignObserverTest.php b/Test/Unit/Observer/AdyenPaymentMethodDataAssignObserverTest.php new file mode 100644 index 0000000000..e987accdd4 --- /dev/null +++ b/Test/Unit/Observer/AdyenPaymentMethodDataAssignObserverTest.php @@ -0,0 +1,160 @@ +checkoutStateDataValidator = $this->createMock(CheckoutStateDataValidator::class); + $this->stateDataCollection = $this->createMock(Collection::class); + $this->stateData = $this->createMock(StateData::class); + $this->vaultHelper = $this->createMock(Vault::class); + $this->paymentInfo = $this->createMock(Payment::class); + $this->observer = new AdyenPaymentMethodDataAssignObserver( + $this->checkoutStateDataValidator, + $this->stateDataCollection, + $this->stateData, + $this->vaultHelper + ); + } + + public function testExecuteWithNoAdditionalData() + { + $dataObject = new DataObject(); + $paymentInfo = $this->createMock(Payment::class); + $observer = $this->getPreparedObserverWithMap([ + [AbstractDataAssignObserver::DATA_CODE, $dataObject], + [AbstractDataAssignObserver::MODEL_CODE, $paymentInfo], + ]); + + $this->observer->execute($observer); + } + + public function testExecuteWithValidAdditionalData() + { + $additionalData = [ + 'brand_code' => 'visa', + 'stateData' => json_encode(['paymentMethod' => ['type' => 'scheme']]), + 'recurringProcessingModel' => 'Subscription', + ]; + + $dataObject = new DataObject([ + PaymentInterface::KEY_ADDITIONAL_DATA => $additionalData, + ]); + + + + $observer = $this->getPreparedObserverWithMap([ + [AbstractDataAssignObserver::DATA_CODE, $dataObject], + [AbstractDataAssignObserver::MODEL_CODE, $this->paymentInfo], + ]); + $this->paymentInfo->expects($this->once())->method('unsAdditionalInformation')->with('cc_type'); + + $this->paymentInfo->method('getData') + ->with('quote_id') + ->willReturn(1); + + $this->vaultHelper->expects($this->once()) + ->method('validateRecurringProcessingModel') + ->with('Subscription') + ->willReturn(true); + + $this->paymentInfo->expects($this->exactly(2))->method('setAdditionalInformation'); + + // Execute the observer logic + $this->observer->execute($observer); + } + + public function testExecuteWithInvalidRecurringProcessingModel() + { + $additionalData = [ + 'brand_code' => 'visa', + 'stateData' => json_encode(['paymentMethod' => ['type' => 'scheme']]), + 'recurringProcessingModel' => 'invalid', + ]; + + $dataObject = new \Magento\Framework\DataObject([ + PaymentInterface::KEY_ADDITIONAL_DATA => $additionalData, + ]); + + $this->paymentInfo->expects($this->atLeastOnce()) + ->method('unsAdditionalInformation') + ->withConsecutive(['cc_type'], ['recurringProcessingModel']); + + $this->paymentInfo->expects($this->any())->method('getData') + ->with('quote_id')->willReturn(123); + + $observer = $this->getPreparedObserverWithMap([ + [AbstractDataAssignObserver::DATA_CODE, $dataObject], + [AbstractDataAssignObserver::MODEL_CODE, $this->paymentInfo], + ]); + + $this->vaultHelper->expects($this->once())->method('validateRecurringProcessingModel') + ->with('invalid')->willReturn(false); + + $this->observer->execute($observer); + } + + public function testExecuteWithStateDataFromDatabase() + { + $this->paymentInfo->expects($this->any())->method('getData') + ->with('quote_id')->willReturn(123); + + $dataObject = new \Magento\Framework\DataObject(); + $observer = $this->getPreparedObserverWithMap([ + [AbstractDataAssignObserver::DATA_CODE, $dataObject], + [AbstractDataAssignObserver::MODEL_CODE, $this->paymentInfo], + ]); + + $this->observer->execute($observer); + } + + /** + * @param array $returnMap + * @return MockObject|Observer + */ + private function getPreparedObserverWithMap(array $returnMap): Observer|MockObject + { + $observer = $this->getMockBuilder(Observer::class) + ->disableOriginalConstructor() + ->getMock(); + $event = $this->getMockBuilder(Event::class) + ->disableOriginalConstructor() + ->getMock(); + + $observer->expects(static::atLeastOnce()) + ->method('getEvent') + ->willReturn($event); + $event->expects(static::atLeastOnce()) + ->method('getDataByKey') + ->willReturnMap( + $returnMap + ); + + return $observer; + } +}