SilentPostTest.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Paypal\Controller\Payflow;
  7. use Magento\Framework\Api\FilterBuilder;
  8. use Magento\Framework\Api\SearchCriteriaBuilder;
  9. use Magento\Framework\DataObject;
  10. use Magento\Framework\Logger\Monolog;
  11. use Magento\Payment\Gateway\Command\CommandException;
  12. use Magento\Paypal\Model\Payflow\Service\Gateway;
  13. use Magento\Paypal\Model\Payflowlink;
  14. use Magento\Sales\Api\Data\OrderInterface;
  15. use Magento\Sales\Api\OrderRepositoryInterface;
  16. use Magento\Sales\Model\Order;
  17. use Magento\Sales\Model\Order\Email\Sender\OrderSender;
  18. use Magento\TestFramework\TestCase\AbstractController;
  19. use PHPUnit\Framework\MockObject_MockObject as MockObject;
  20. class SilentPostTest extends AbstractController
  21. {
  22. /**
  23. * @var Gateway|MockObject
  24. */
  25. private $gateway;
  26. /**
  27. * @var OrderSender|MockObject
  28. */
  29. private $orderSender;
  30. /**
  31. * @inheritdoc
  32. */
  33. protected function setUp()
  34. {
  35. parent::setUp();
  36. $this->gateway = $this->getMockBuilder(Gateway::class)
  37. ->disableOriginalConstructor()
  38. ->getMock();
  39. $this->orderSender = $this->getMockBuilder(OrderSender::class)
  40. ->disableOriginalConstructor()
  41. ->getMock();
  42. $this->_objectManager->addSharedInstance($this->gateway, Gateway::class);
  43. $this->_objectManager->addSharedInstance($this->orderSender, OrderSender::class);
  44. }
  45. /**
  46. * @inheritdoc
  47. */
  48. protected function tearDown()
  49. {
  50. $this->_objectManager->removeSharedInstance(Gateway::class);
  51. $this->_objectManager->removeSharedInstance(OrderSender::class);
  52. parent::tearDown();
  53. }
  54. /**
  55. * Checks a test case when Payflow Link callback action receives Silent Post notification with transaction details.
  56. *
  57. * @param int $resultCode
  58. * @param string $orderState
  59. * @param string $orderStatus
  60. * @magentoDataFixture Magento/Paypal/_files/order_payflow_link.php
  61. * @dataProvider responseCodeDataProvider
  62. */
  63. public function testSuccessfulNotification($resultCode, $orderState, $orderStatus)
  64. {
  65. $orderIncrementId = '000000045';
  66. $this->withRequest($orderIncrementId, $resultCode);
  67. $this->withGatewayResponse($orderIncrementId, $resultCode);
  68. $this->dispatch('paypal/payflow/silentPost');
  69. self::assertEquals(200, $this->getResponse()->getStatusCode());
  70. $order = $this->getOrder($orderIncrementId);
  71. self::assertEquals($orderState, $order->getState());
  72. self::assertEquals($orderStatus, $order->getStatus());
  73. }
  74. /**
  75. * Get list of different variations for Silent Post action testing,
  76. * like different response codes from PayPal.
  77. *
  78. * @return array
  79. */
  80. public function responseCodeDataProvider()
  81. {
  82. return [
  83. [Payflowlink::RESPONSE_CODE_APPROVED, Order::STATE_COMPLETE, Order::STATE_COMPLETE],
  84. [Payflowlink::RESPONSE_CODE_FRAUDSERVICE_FILTER, Order::STATE_PAYMENT_REVIEW, Order::STATUS_FRAUD],
  85. ];
  86. }
  87. /**
  88. * Checks a test case when Payflow Link callback receives Silent Post notification from PayPal
  89. * with fraudulent transaction and PayPal gateway configured to reject this kind of transactions.
  90. *
  91. * @magentoDataFixture Magento/Paypal/_files/order_payflow_link.php
  92. */
  93. public function testFraudulentNotification()
  94. {
  95. $orderIncrementId = '000000045';
  96. $resultCode = Payflowlink::RESPONSE_CODE_DECLINED_BY_FILTER;
  97. $this->withRequest($orderIncrementId, $resultCode);
  98. $this->withGatewayResponse($orderIncrementId, $resultCode);
  99. $logger = $this->getMockBuilder(Monolog::class)
  100. ->disableOriginalConstructor()
  101. ->getMock();
  102. $this->_objectManager->addSharedInstance($logger, Monolog::class);
  103. $exception = new CommandException(__('Response message from PayPal gateway'));
  104. $logger->expects(self::once())
  105. ->method('critical')
  106. ->with(self::equalTo($exception));
  107. $this->dispatch('paypal/payflow/silentPost');
  108. self::assertEquals(200, $this->getResponse()->getStatusCode());
  109. $this->_objectManager->removeSharedInstance(Monolog::class);
  110. }
  111. /**
  112. * Imitates real POST request with test data.
  113. *
  114. * @param string $orderIncrementId
  115. * @param int $resultCode
  116. * @return void
  117. */
  118. private function withRequest($orderIncrementId, $resultCode)
  119. {
  120. $data = [
  121. 'INVNUM' => $orderIncrementId,
  122. 'AMT' => 100,
  123. 'PNREF' => 'A21CP234KLB8',
  124. 'USER2' => 'cf7i85d01ed7c92223031afb4rdl2f1f',
  125. 'RESULT' => $resultCode,
  126. 'TYPE' => 'A',
  127. ];
  128. $this->getRequest()->setPostValue($data);
  129. }
  130. /**
  131. * Imitates response from PayPal gateway.
  132. *
  133. * @param string $orderIncrementId
  134. * @param int $resultCode
  135. * @return void
  136. */
  137. private function withGatewayResponse($orderIncrementId, $resultCode)
  138. {
  139. $response = new DataObject([
  140. 'custref' => $orderIncrementId,
  141. 'origresult' => $resultCode,
  142. 'respmsg' => 'Response message from PayPal gateway'
  143. ]);
  144. $this->gateway->method('postRequest')
  145. ->willReturn($response);
  146. }
  147. /**
  148. * Gets order stored by fixture.
  149. *
  150. * @param string $incrementId
  151. * @return OrderInterface
  152. */
  153. private function getOrder($incrementId)
  154. {
  155. /** @var FilterBuilder $filterBuilder */
  156. $filterBuilder = $this->_objectManager->get(FilterBuilder::class);
  157. $filters = [
  158. $filterBuilder->setField(OrderInterface::INCREMENT_ID)
  159. ->setValue($incrementId)
  160. ->create()
  161. ];
  162. /** @var SearchCriteriaBuilder $searchCriteriaBuilder */
  163. $searchCriteriaBuilder = $this->_objectManager->get(SearchCriteriaBuilder::class);
  164. $searchCriteria = $searchCriteriaBuilder->addFilters($filters)
  165. ->create();
  166. $orderRepository = $this->_objectManager->get(OrderRepositoryInterface::class);
  167. $orders = $orderRepository->getList($searchCriteria)
  168. ->getItems();
  169. /** @var OrderInterface $order */
  170. return array_pop($orders);
  171. }
  172. }