285 lines
10 KiB
PHP
Executable File
285 lines
10 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Copyright © Magento, Inc. All rights reserved.
|
|
* See COPYING.txt for license details.
|
|
*/
|
|
namespace Magento\Paypal\Model;
|
|
|
|
use Magento\Framework\Api\SearchCriteriaBuilder;
|
|
use Magento\Sales\Api\Data\OrderInterface;
|
|
use Magento\Sales\Api\OrderRepositoryInterface;
|
|
use Magento\Sales\Model\Order;
|
|
use Magento\Sales\Model\Order\Creditmemo;
|
|
use Magento\Sales\Model\Order\Invoice;
|
|
use Magento\TestFramework\Helper\Bootstrap;
|
|
|
|
/**
|
|
* @magentoAppArea frontend
|
|
*/
|
|
class IpnTest extends \PHPUnit\Framework\TestCase
|
|
{
|
|
/**
|
|
* @var \Magento\Framework\ObjectManagerInterface
|
|
*/
|
|
protected $_objectManager;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
$this->_objectManager = Bootstrap::getObjectManager();
|
|
}
|
|
|
|
/**
|
|
* @param string $currencyCode
|
|
* @dataProvider currencyProvider
|
|
* @magentoDataFixture Magento/Paypal/_files/order_express.php
|
|
* @magentoConfigFixture current_store payment/paypal_direct/active 1
|
|
* @magentoConfigFixture current_store payment/paypal_express/active 1
|
|
* @magentoConfigFixture current_store paypal/general/merchant_country US
|
|
*/
|
|
public function testProcessIpnRequestExpressCurrency($currencyCode)
|
|
{
|
|
$this->_processIpnRequestCurrency($currencyCode);
|
|
}
|
|
|
|
/**
|
|
* Refund full order amount by Paypal Express IPN message service.
|
|
*
|
|
* @magentoDataFixture Magento/Paypal/_files/order_express_with_invoice_and_shipping.php
|
|
* @magentoConfigFixture current_store payment/paypal_express/active 1
|
|
* @magentoConfigFixture current_store paypal/general/merchant_country US
|
|
*/
|
|
public function testProcessIpnRequestFullRefund()
|
|
{
|
|
$ipnData = require __DIR__ . '/../_files/ipn_refund.php';
|
|
$ipnFactory = $this->_objectManager->create(IpnFactory::class);
|
|
$ipnModel = $ipnFactory->create(
|
|
[
|
|
'data' => $ipnData,
|
|
'curlFactory' => $this->_createMockedHttpAdapter()
|
|
]
|
|
);
|
|
|
|
$ipnModel->processIpnRequest();
|
|
|
|
$order = $this->_objectManager->create(Order::class);
|
|
$order->loadByIncrementId('100000001');
|
|
|
|
$creditmemoItems = $order->getCreditmemosCollection()->getItems();
|
|
$creditmemo = current($creditmemoItems);
|
|
|
|
$this->assertEquals(Order::STATE_CLOSED, $order->getState()) ;
|
|
$this->assertCount(1, $creditmemoItems);
|
|
$this->assertEquals(Creditmemo::STATE_REFUNDED, $creditmemo->getState());
|
|
$this->assertEquals(10, $order->getSubtotalRefunded());
|
|
$this->assertEquals(10, $order->getBaseSubtotalRefunded());
|
|
$this->assertEquals(20, $order->getShippingRefunded());
|
|
$this->assertEquals(20, $order->getBaseShippingRefunded());
|
|
$this->assertEquals(30, $order->getTotalRefunded());
|
|
$this->assertEquals(30, $order->getBaseTotalRefunded());
|
|
$this->assertEquals(30, $order->getTotalOnlineRefunded());
|
|
$this->assertEmpty($order->getTotalOfflineRefunded());
|
|
}
|
|
|
|
/**
|
|
* Partial refund of order amount by Paypal Express IPN message service.
|
|
*
|
|
* @magentoDataFixture Magento/Paypal/_files/order_express_with_invoice_and_shipping.php
|
|
* @magentoConfigFixture current_store payment/paypal_express/active 1
|
|
* @magentoConfigFixture current_store paypal/general/merchant_country US
|
|
*/
|
|
public function testProcessIpnRequestPartialRefund()
|
|
{
|
|
$ipnData = require __DIR__ . '/../_files/ipn_refund.php';
|
|
|
|
$refundAmount = -15;
|
|
$ipnData['mc_gross'] = $refundAmount;
|
|
|
|
$ipnFactory = $this->_objectManager->create(IpnFactory::class);
|
|
$ipnModel = $ipnFactory->create(
|
|
[
|
|
'data' => $ipnData,
|
|
'curlFactory' => $this->_createMockedHttpAdapter()
|
|
]
|
|
);
|
|
|
|
$ipnModel->processIpnRequest();
|
|
|
|
$order = $this->_objectManager->create(Order::class);
|
|
$order->loadByIncrementId('100000001');
|
|
|
|
$creditmemoItems = $order->getCreditmemosCollection()->getItems();
|
|
$comments = $order->load($order->getId())->getAllStatusHistory();
|
|
$commentData = reset($comments);
|
|
$commentOrigin = sprintf(
|
|
'IPN "Refunded". Refund issued by merchant. Registered notification about refunded amount of $%d.00. '.
|
|
'Transaction ID: "%s". Credit Memo has not been created. Please create offline Credit Memo.',
|
|
abs($refundAmount),
|
|
$ipnData['txn_id']
|
|
);
|
|
|
|
$this->assertEquals(Order::STATE_PROCESSING, $order->getState()) ;
|
|
$this->assertEmpty(count($creditmemoItems));
|
|
$this->assertCount(1, $comments);
|
|
$this->assertEquals($commentOrigin, $commentData->getComment());
|
|
}
|
|
|
|
/**
|
|
* Refund rest of order amount by Paypal Express IPN message service.
|
|
*
|
|
* @magentoDataFixture Magento/Paypal/_files/order_express_with_invoice_and_shipping.php
|
|
* @magentoConfigFixture current_store payment/paypal_express/active 1
|
|
* @magentoConfigFixture current_store paypal/general/merchant_country US
|
|
*/
|
|
public function testProcessIpnRequestRestRefund()
|
|
{
|
|
$ipnData = require __DIR__ . '/../_files/ipn_refund.php';
|
|
|
|
$ipnFactory = $this->_objectManager->create(IpnFactory::class);
|
|
$ipnModel = $ipnFactory->create(
|
|
[
|
|
'data' => $ipnData,
|
|
'curlFactory' => $this->_createMockedHttpAdapter()
|
|
]
|
|
);
|
|
|
|
$ipnModel->processIpnRequest();
|
|
|
|
$order = $this->_objectManager->create(Order::class);
|
|
$order->loadByIncrementId('100000001');
|
|
|
|
$creditmemoItems = $order->getCreditmemosCollection()->getItems();
|
|
|
|
$this->assertEquals(Order::STATE_CLOSED, $order->getState()) ;
|
|
$this->assertCount(1, $creditmemoItems);
|
|
$this->assertEquals(10, $order->getSubtotalRefunded());
|
|
$this->assertEquals(10, $order->getBaseSubtotalRefunded());
|
|
$this->assertEquals(20, $order->getShippingRefunded());
|
|
$this->assertEquals(20, $order->getBaseShippingRefunded());
|
|
$this->assertEquals(30, $order->getTotalRefunded());
|
|
$this->assertEquals(30, $order->getBaseTotalRefunded());
|
|
$this->assertEquals(30, $order->getTotalOnlineRefunded());
|
|
$this->assertEmpty($order->getTotalOfflineRefunded());
|
|
}
|
|
|
|
/**
|
|
* Verifies canceling an order that was in payment review state by PayPal Express IPN message service.
|
|
*
|
|
* @magentoDataFixture Magento/Paypal/_files/order_express_with_invoice_payment_review.php
|
|
* @magentoConfigFixture current_store payment/paypal_express/active 1
|
|
* @magentoConfigFixture current_store paypal/general/merchant_country US
|
|
*/
|
|
public function testProcessIpnRequestWithFailedStatus()
|
|
{
|
|
$ipnData = require __DIR__ . '/../_files/ipn_failed.php';
|
|
|
|
/** @var IpnFactory $ipnFactory */
|
|
$ipnFactory = $this->_objectManager->create(IpnFactory::class);
|
|
$ipnModel = $ipnFactory->create(
|
|
[
|
|
'data' => $ipnData,
|
|
'curlFactory' => $this->_createMockedHttpAdapter()
|
|
]
|
|
);
|
|
|
|
$ipnModel->processIpnRequest();
|
|
|
|
$order = $this->getOrder($ipnData['invoice']);
|
|
$invoiceItems = $order->getInvoiceCollection()
|
|
->getItems();
|
|
/** @var Invoice $invoice */
|
|
$invoice = array_pop($invoiceItems);
|
|
$invoice->getState();
|
|
|
|
$this->assertEquals(Order::STATE_CANCELED, $order->getState());
|
|
$this->assertEquals(Invoice::STATE_CANCELED, $invoice->getState());
|
|
}
|
|
|
|
/**
|
|
* Test processIpnRequest() currency check for paypal_express and paypal_standard payment methods
|
|
*
|
|
* @param string $currencyCode
|
|
*/
|
|
protected function _processIpnRequestCurrency($currencyCode)
|
|
{
|
|
$ipnData = require __DIR__ . '/../_files/ipn.php';
|
|
$ipnData['mc_currency'] = $currencyCode;
|
|
|
|
/** @var $ipnFactory \Magento\Paypal\Model\IpnFactory */
|
|
$ipnFactory = $this->_objectManager->create(\Magento\Paypal\Model\IpnFactory::class);
|
|
|
|
$model = $ipnFactory->create(['data' => $ipnData, 'curlFactory' => $this->_createMockedHttpAdapter()]);
|
|
$model->processIpnRequest();
|
|
|
|
$order = $this->_objectManager->create(\Magento\Sales\Model\Order::class);
|
|
$order->loadByIncrementId('100000001');
|
|
$this->_assertOrder($order, $currencyCode);
|
|
}
|
|
|
|
/**
|
|
* Perform order state and status assertions depending on currency code
|
|
*
|
|
* @param \Magento\Sales\Model\Order $order
|
|
* @param string $currencyCode
|
|
*/
|
|
protected function _assertOrder($order, $currencyCode)
|
|
{
|
|
if ($currencyCode == 'USD') {
|
|
$this->assertEquals('complete', $order->getState());
|
|
$this->assertEquals('complete', $order->getStatus());
|
|
} else {
|
|
$this->assertEquals('payment_review', $order->getState());
|
|
$this->assertEquals('fraud', $order->getStatus());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Data provider for currency check tests
|
|
*
|
|
* @static
|
|
* @return array
|
|
*/
|
|
public static function currencyProvider()
|
|
{
|
|
return [['USD'], ['EUR']];
|
|
}
|
|
|
|
/**
|
|
* Mocked HTTP adapter to get VERIFIED PayPal IPN postback result
|
|
*
|
|
* @return \Magento\Framework\HTTP\Adapter\Curl
|
|
*/
|
|
protected function _createMockedHttpAdapter()
|
|
{
|
|
$factory = $this->createPartialMock(\Magento\Framework\HTTP\Adapter\CurlFactory::class, ['create']);
|
|
$adapter = $this->createPartialMock(\Magento\Framework\HTTP\Adapter\Curl::class, ['read', 'write']);
|
|
|
|
$adapter->expects($this->once())->method('read')->with()->willReturn("\nVERIFIED");
|
|
|
|
$adapter->expects($this->once())->method('write');
|
|
|
|
$factory->expects($this->once())->method('create')->with()->willReturn($adapter);
|
|
return $factory;
|
|
}
|
|
|
|
/**
|
|
* Get stored order.
|
|
*
|
|
* @param string $incrementId
|
|
* @return OrderInterface
|
|
*/
|
|
private function getOrder(string $incrementId)
|
|
{
|
|
/** @var SearchCriteriaBuilder $searchCriteriaBuilder */
|
|
$searchCriteriaBuilder = $this->_objectManager->get(SearchCriteriaBuilder::class);
|
|
$searchCriteria = $searchCriteriaBuilder->addFilter(OrderInterface::INCREMENT_ID, $incrementId)
|
|
->create();
|
|
|
|
$orderRepository = $this->_objectManager->get(OrderRepositoryInterface::class);
|
|
$orders = $orderRepository->getList($searchCriteria)
|
|
->getItems();
|
|
|
|
/** @var OrderInterface $order */
|
|
return array_pop($orders);
|
|
}
|
|
}
|