PaymentTest.php 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Sales\Test\Unit\Model\Order;
  7. use Magento\Framework\Model\Context;
  8. use Magento\Payment\Helper\Data;
  9. use Magento\Payment\Model\Method\AbstractMethod;
  10. use Magento\Sales\Api\CreditmemoManagementInterface;
  11. use Magento\Sales\Model\Order;
  12. use Magento\Sales\Model\Order\Creditmemo;
  13. use Magento\Sales\Model\Order\Invoice;
  14. use Magento\Sales\Model\Order\OrderStateResolverInterface;
  15. use Magento\Sales\Model\Order\Payment;
  16. use Magento\Sales\Model\Order\Payment\Transaction;
  17. use PHPUnit_Framework_MockObject_MockObject as MockObject;
  18. /**
  19. * Class PaymentTest
  20. *
  21. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  22. * @SuppressWarnings(PHPMD.TooManyFields)
  23. */
  24. class PaymentTest extends \PHPUnit\Framework\TestCase
  25. {
  26. const TRANSACTION_ID = 'ewr34fM49V0';
  27. /**
  28. * @var Context|MockObject
  29. */
  30. private $context;
  31. /**
  32. * @var OrderStateResolverInterface|MockObject
  33. */
  34. private $orderStateResolver;
  35. /**
  36. * @var Payment
  37. */
  38. private $payment;
  39. /**
  40. * @var Data|MockObject
  41. */
  42. private $helper;
  43. /**
  44. * @var \Magento\Framework\Event\Manager | \PHPUnit_Framework_MockObject_MockObject
  45. */
  46. protected $eventManagerMock;
  47. /**
  48. * @var \Magento\Directory\Model\PriceCurrency | \PHPUnit_Framework_MockObject_MockObject
  49. */
  50. protected $priceCurrencyMock;
  51. /**
  52. * @var \Magento\Directory\Model\Currency | \PHPUnit_Framework_MockObject_MockObject
  53. */
  54. protected $currencyMock;
  55. /**
  56. * @var Order|MockObject
  57. */
  58. private $order;
  59. /**
  60. * @var AbstractMethod|MockObject
  61. */
  62. private $paymentMethod;
  63. /**
  64. * @var Invoice|MockObject
  65. */
  66. private $invoice;
  67. /**
  68. * @var string
  69. */
  70. private $transactionId;
  71. /**
  72. * @var \PHPUnit_Framework_MockObject_MockObject
  73. */
  74. protected $transactionCollectionFactory;
  75. /**
  76. * @var \Magento\Sales\Model\Order\CreditmemoFactory|\PHPUnit_Framework_MockObject_MockObject
  77. */
  78. protected $creditmemoFactoryMock;
  79. /**
  80. * @var \Magento\Sales\Model\Order\Creditmemo | \PHPUnit_Framework_MockObject_MockObject
  81. */
  82. protected $creditMemoMock;
  83. /**
  84. * @var \Magento\Sales\Model\Order\Payment\Transaction\Repository | \PHPUnit_Framework_MockObject_MockObject
  85. */
  86. protected $transactionRepositoryMock;
  87. /**
  88. * @var \Magento\Sales\Model\Order\Payment\Transaction\ManagerInterface| \PHPUnit_Framework_MockObject_MockObject
  89. */
  90. protected $transactionManagerMock;
  91. /**
  92. * @var \Magento\Sales\Model\Order\Payment\Transaction\BuilderInterface | \PHPUnit_Framework_MockObject_MockObject
  93. */
  94. protected $transactionBuilderMock;
  95. /**
  96. * @var \Magento\Sales\Model\Order\Payment\Processor|\PHPUnit_Framework_MockObject_MockObject
  97. */
  98. protected $paymentProcessor;
  99. /**
  100. * @var \Magento\Sales\Model\OrderRepository|\PHPUnit_Framework_MockObject_MockObject
  101. */
  102. protected $orderRepository;
  103. /**
  104. * @var CreditmemoManagementInterface
  105. */
  106. private $creditmemoManagerMock;
  107. /**
  108. * @return void
  109. * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
  110. * @SuppressWarnings(PHPMD.TooManyFields)
  111. */
  112. protected function setUp()
  113. {
  114. $this->eventManagerMock = $this->getMockBuilder(\Magento\Framework\Event\Manager::class)
  115. ->disableOriginalConstructor()
  116. ->getMock();
  117. $this->context = $this->getMockBuilder(Context::class)
  118. ->disableOriginalConstructor()
  119. ->getMock();
  120. $this->context->expects($this->atLeastOnce())
  121. ->method('getEventDispatcher')
  122. ->will($this->returnValue($this->eventManagerMock));
  123. $this->helper = $this->getMockBuilder(Data::class)
  124. ->disableOriginalConstructor()
  125. ->setMethods(['getMethodInstance'])
  126. ->getMock();
  127. $this->priceCurrencyMock = $this->getMockBuilder(\Magento\Directory\Model\PriceCurrency::class)
  128. ->disableOriginalConstructor()
  129. ->setMethods(['format'])
  130. ->getMock();
  131. $this->currencyMock = $this->getMockBuilder(\Magento\Directory\Model\Currency::class)
  132. ->disableOriginalConstructor()
  133. ->setMethods(['formatTxt'])
  134. ->getMock();
  135. $transaction = \Magento\Sales\Model\Order\Payment\Transaction\Repository::class;
  136. $this->transactionRepositoryMock = $this->getMockBuilder($transaction)
  137. ->disableOriginalConstructor()
  138. ->setMethods(['get', 'getByTransactionType', 'getByTransactionId'])
  139. ->getMock();
  140. $this->paymentProcessor = $this->createMock(\Magento\Sales\Model\Order\Payment\Processor::class);
  141. $this->orderRepository = $this->createPartialMock(\Magento\Sales\Model\OrderRepository::class, ['get']);
  142. $this->priceCurrencyMock->expects($this->any())
  143. ->method('format')
  144. ->willReturnCallback(
  145. function ($value) {
  146. return $value;
  147. }
  148. );
  149. $this->paymentMethod = $this->getMockBuilder(AbstractMethod::class)
  150. ->disableOriginalConstructor()
  151. ->setMethods(
  152. [
  153. 'canVoid',
  154. 'authorize',
  155. 'getConfigData',
  156. 'getConfigPaymentAction',
  157. 'validate',
  158. 'setStore',
  159. 'acceptPayment',
  160. 'denyPayment',
  161. 'fetchTransactionInfo',
  162. 'canCapture',
  163. 'canRefund',
  164. 'canOrder',
  165. 'order',
  166. 'isInitializeNeeded',
  167. 'initialize',
  168. 'refund'
  169. ]
  170. )
  171. ->getMock();
  172. $this->invoice = $this->getMockBuilder(Invoice::class)
  173. ->disableOriginalConstructor()
  174. ->setMethods(
  175. [
  176. 'getTransactionId',
  177. 'load',
  178. 'getId',
  179. 'pay',
  180. 'cancel',
  181. 'getGrandTotal',
  182. 'getBaseGrandTotal',
  183. 'getShippingAmount',
  184. 'getBaseShippingAmount',
  185. 'getBaseTotalRefunded',
  186. 'getItemsCollection',
  187. 'getOrder',
  188. 'register',
  189. 'capture',
  190. ]
  191. )
  192. ->getMock();
  193. $this->helper->method('getMethodInstance')
  194. ->will($this->returnValue($this->paymentMethod));
  195. $this->order = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
  196. ->disableOriginalConstructor()
  197. ->setMethods(
  198. [
  199. 'getConfig',
  200. 'setState',
  201. 'setStatus',
  202. 'getStoreId',
  203. 'getBaseGrandTotal',
  204. 'getBaseCurrency',
  205. 'getBaseCurrencyCode',
  206. 'getTotalDue',
  207. 'getBaseTotalDue',
  208. 'getInvoiceCollection',
  209. 'addRelatedObject',
  210. 'getState',
  211. 'getStatus',
  212. 'addStatusHistoryComment',
  213. 'registerCancellation',
  214. 'getCustomerNote',
  215. 'prepareInvoice',
  216. 'getPaymentsCollection',
  217. 'setIsCustomerNotified'
  218. ]
  219. )
  220. ->getMock();
  221. $this->transactionCollectionFactory = $this->getMockBuilder(
  222. \Magento\Sales\Model\ResourceModel\Order\Payment\Transaction\CollectionFactory::class
  223. )
  224. ->setMethods(['create'])
  225. ->getMock();
  226. $this->creditmemoFactoryMock = $this->createMock(\Magento\Sales\Model\Order\CreditmemoFactory::class);
  227. $this->transactionManagerMock = $this->createMock(
  228. \Magento\Sales\Model\Order\Payment\Transaction\Manager::class
  229. );
  230. $this->transactionBuilderMock = $this->createMock(
  231. \Magento\Sales\Model\Order\Payment\Transaction\Builder::class
  232. );
  233. $this->orderStateResolver = $this->getMockBuilder(Order\OrderStateResolverInterface::class)
  234. ->disableOriginalConstructor()
  235. ->getMockForAbstractClass();
  236. $this->creditMemoMock = $this->getMockBuilder(Creditmemo::class)
  237. ->disableOriginalConstructor()
  238. ->setMethods(
  239. [
  240. 'setPaymentRefundDisallowed',
  241. 'getItemsCollection',
  242. 'getItems',
  243. 'setAutomaticallyCreated',
  244. 'register',
  245. 'addComment',
  246. 'save',
  247. 'getGrandTotal',
  248. 'getBaseGrandTotal',
  249. 'getDoTransaction',
  250. 'getInvoice',
  251. 'getOrder',
  252. 'getPaymentRefundDisallowed'
  253. ]
  254. )
  255. ->getMock();
  256. $this->creditmemoManagerMock = $this->getMockBuilder(CreditmemoManagementInterface::class)
  257. ->disableOriginalConstructor()
  258. ->getMockForAbstractClass();
  259. $this->payment = $this->initPayment();
  260. $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
  261. $helper->setBackwardCompatibleProperty($this->payment, 'orderStateResolver', $this->orderStateResolver);
  262. $this->payment->setMethod('any');
  263. $this->payment->setOrder($this->order);
  264. $this->transactionId = self::TRANSACTION_ID;
  265. }
  266. protected function tearDown()
  267. {
  268. unset($this->payment);
  269. }
  270. public function testCancel()
  271. {
  272. $this->helper->expects($this->once())
  273. ->method('getMethodInstance')
  274. ->will($this->returnValue($this->paymentMethod));
  275. // check fix for partial refunds in Payflow Pro
  276. $this->paymentMethod->expects($this->once())
  277. ->method('canVoid')
  278. ->willReturn(false);
  279. $this->assertEquals($this->payment, $this->payment->cancel());
  280. }
  281. public function testPlace()
  282. {
  283. $newOrderStatus = 'new_status';
  284. $this->helper->expects($this->once())
  285. ->method('getMethodInstance')
  286. ->will($this->returnValue($this->paymentMethod));
  287. $this->paymentMethod->expects($this->any())
  288. ->method('getConfigData')
  289. ->with('order_status', null)
  290. ->willReturn($newOrderStatus);
  291. $this->mockGetDefaultStatus(Order::STATE_NEW, $newOrderStatus, ['first', 'second']);
  292. $this->assertOrderUpdated(Order::STATE_NEW, $newOrderStatus);
  293. $this->paymentMethod->expects($this->once())
  294. ->method('getConfigPaymentAction')
  295. ->willReturn(null);
  296. $this->mockPlaceEvents();
  297. $this->assertEquals($this->payment, $this->payment->place());
  298. }
  299. public function testPlaceActionOrder()
  300. {
  301. $newOrderStatus = 'new_status';
  302. $customerNote = 'blabla';
  303. $sum = 10;
  304. $this->payment->setTransactionId($this->transactionId);
  305. $this->order->expects($this->any())->method('getTotalDue')->willReturn($sum);
  306. $this->order->expects($this->any())->method('getBaseTotalDue')->willReturn($sum);
  307. $this->helper->expects($this->once())
  308. ->method('getMethodInstance')
  309. ->will($this->returnValue($this->paymentMethod));
  310. $this->paymentMethod->expects($this->once())
  311. ->method('getConfigPaymentAction')
  312. ->willReturn(\Magento\Payment\Model\Method\AbstractMethod::ACTION_ORDER);
  313. $this->paymentMethod->expects($this->once())->method('isInitializeNeeded')->willReturn(false);
  314. $this->paymentMethod->expects($this->any())
  315. ->method('getConfigData')
  316. ->with('order_status', null)
  317. ->willReturn($newOrderStatus);
  318. $this->mockGetDefaultStatus(Order::STATE_PROCESSING, $newOrderStatus, ['first', 'second']);
  319. $this->order->expects($this->any())
  320. ->method('setState')
  321. ->with(Order::STATE_PROCESSING)
  322. ->willReturnSelf();
  323. $this->order->expects($this->any())
  324. ->method('setStatus')
  325. ->with($newOrderStatus)
  326. ->willReturnSelf();
  327. $this->paymentProcessor->expects($this->once())
  328. ->method('order')
  329. ->with($this->payment, $sum)
  330. ->willReturnSelf();
  331. $this->mockPlaceEvents();
  332. $statusHistory = $this->getMockForAbstractClass(
  333. \Magento\Sales\Api\Data\OrderStatusHistoryInterface::class
  334. );
  335. $this->order->expects($this->any())->method('getCustomerNote')->willReturn($customerNote);
  336. $this->order->expects($this->any())
  337. ->method('addStatusHistoryComment')
  338. ->withConsecutive(
  339. [$customerNote]
  340. )
  341. ->willReturn($statusHistory);
  342. $this->order->expects($this->any())
  343. ->method('setIsCustomerNotified')
  344. ->with(true)
  345. ->willReturn($statusHistory);
  346. $this->assertEquals($this->payment, $this->payment->place());
  347. }
  348. protected function mockPlaceEvents()
  349. {
  350. $this->eventManagerMock->expects($this->at(0))
  351. ->method('dispatch')
  352. ->with('sales_order_payment_place_start', ['payment' => $this->payment]);
  353. $this->eventManagerMock->expects($this->at(1))
  354. ->method('dispatch')
  355. ->with('sales_order_payment_place_end', ['payment' => $this->payment]);
  356. }
  357. public function testPlaceActionAuthorizeInitializeNeeded()
  358. {
  359. $newOrderStatus = 'new_status';
  360. $customerNote = 'blabla';
  361. $sum = 10;
  362. $this->order->expects($this->any())->method('getBaseGrandTotal')->willReturn($sum);
  363. $this->order->expects($this->any())->method('getTotalDue')->willReturn($sum);
  364. $this->order->expects($this->any())->method('getBaseTotalDue')->willReturn($sum);
  365. $this->helper->expects($this->once())
  366. ->method('getMethodInstance')
  367. ->will($this->returnValue($this->paymentMethod));
  368. $this->paymentMethod->expects($this->once())
  369. ->method('getConfigPaymentAction')
  370. ->willReturn(\Magento\Payment\Model\Method\AbstractMethod::ACTION_AUTHORIZE);
  371. $this->paymentMethod->expects($this->any())
  372. ->method('getConfigData')
  373. ->withConsecutive(
  374. ['order_status'],
  375. ['payment_action']
  376. )->willReturn($newOrderStatus);
  377. $this->paymentMethod->expects($this->once())->method('isInitializeNeeded')->willReturn(true);
  378. $this->paymentMethod->expects($this->once())->method('initialize');
  379. $this->mockGetDefaultStatus(Order::STATE_NEW, $newOrderStatus, ['first', 'second']);
  380. $this->order->expects($this->any())
  381. ->method('setState')
  382. ->with(Order::STATE_NEW)
  383. ->willReturnSelf();
  384. $this->order->expects($this->any())
  385. ->method('setStatus')
  386. ->with($newOrderStatus)
  387. ->willReturnSelf();
  388. $this->mockPlaceEvents();
  389. $statusHistory = $this->getMockForAbstractClass(
  390. \Magento\Sales\Api\Data\OrderStatusHistoryInterface::class
  391. );
  392. $this->order->expects($this->any())->method('getCustomerNote')->willReturn($customerNote);
  393. $this->order->expects($this->any())
  394. ->method('addStatusHistoryComment')
  395. ->withConsecutive(
  396. [$customerNote],
  397. [__('Authorized amount of %1', $sum)]
  398. )
  399. ->willReturn($statusHistory);
  400. $this->order->expects($this->any())
  401. ->method('setIsCustomerNotified')
  402. ->with(true)
  403. ->willReturn($statusHistory);
  404. $this->assertEquals($this->payment, $this->payment->place());
  405. }
  406. public function testPlaceActionAuthorizeFraud()
  407. {
  408. $newOrderStatus = 'new_status';
  409. $customerNote = 'blabla';
  410. $sum = 10;
  411. $this->order->expects($this->any())->method('getTotalDue')->willReturn($sum);
  412. $this->order->expects($this->any())->method('getBaseTotalDue')->willReturn($sum);
  413. $this->helper->expects($this->once())
  414. ->method('getMethodInstance')
  415. ->will($this->returnValue($this->paymentMethod));
  416. $this->payment->setTransactionId($this->transactionId);
  417. $this->paymentMethod->expects($this->once())
  418. ->method('getConfigPaymentAction')
  419. ->willReturn(\Magento\Payment\Model\Method\AbstractMethod::ACTION_AUTHORIZE);
  420. $this->paymentMethod->expects($this->any())
  421. ->method('getConfigData')
  422. ->with('order_status', null)
  423. ->willReturn($newOrderStatus);
  424. $statusHistory = $this->getMockForAbstractClass(
  425. \Magento\Sales\Api\Data\OrderStatusHistoryInterface::class
  426. );
  427. $this->order->expects($this->any())->method('getCustomerNote')->willReturn($customerNote);
  428. $this->order->expects($this->any())
  429. ->method('addStatusHistoryComment')
  430. ->with($customerNote)
  431. ->willReturn($statusHistory);
  432. $this->mockGetDefaultStatus(Order::STATE_PROCESSING, Order::STATUS_FRAUD, ['first', 'second']);
  433. $this->order->expects($this->any())
  434. ->method('setState')
  435. ->with(Order::STATE_PROCESSING)
  436. ->willReturnSelf();
  437. $this->order->expects($this->any())
  438. ->method('setStatus')
  439. ->withConsecutive(
  440. [Order::STATUS_FRAUD]
  441. )->willReturnSelf();
  442. $this->order->expects($this->atLeastOnce())
  443. ->method('getStatus')
  444. ->willReturn(Order::STATUS_FRAUD);
  445. $this->paymentMethod->expects($this->once())
  446. ->method('getConfigPaymentAction')
  447. ->willReturn(null);
  448. $this->assertEquals($this->payment, $this->payment->place());
  449. //maybe we don't need write authorised sum when fraud was detected
  450. $this->assertEquals($sum, $this->payment->getAmountAuthorized());
  451. }
  452. public function testPlaceActionAuthorizeCapture()
  453. {
  454. $newOrderStatus = 'new_status';
  455. $customerNote = 'blabla';
  456. $sum = 10;
  457. $this->order->expects($this->any())->method('getTotalDue')->willReturn($sum);
  458. $this->order->expects($this->any())->method('getBaseTotalDue')->willReturn($sum);
  459. $this->helper->expects($this->once())
  460. ->method('getMethodInstance')
  461. ->will($this->returnValue($this->paymentMethod));
  462. $this->paymentMethod->expects($this->once())
  463. ->method('getConfigPaymentAction')
  464. ->willReturn(\Magento\Payment\Model\Method\AbstractMethod::ACTION_AUTHORIZE_CAPTURE);
  465. $this->paymentMethod->expects($this->any())
  466. ->method('getConfigData')
  467. ->with('order_status', null)
  468. ->willReturn($newOrderStatus);
  469. $statusHistory = $this->getMockForAbstractClass(
  470. \Magento\Sales\Api\Data\OrderStatusHistoryInterface::class
  471. );
  472. $this->order->expects($this->any())->method('getCustomerNote')->willReturn($customerNote);
  473. $this->order->expects($this->any())
  474. ->method('addStatusHistoryComment')
  475. ->with($customerNote)
  476. ->willReturn($statusHistory);
  477. $this->mockGetDefaultStatus(Order::STATE_PROCESSING, $newOrderStatus, ['first', 'second']);
  478. $this->order->expects($this->any())
  479. ->method('setState')
  480. ->with(Order::STATE_PROCESSING)
  481. ->willReturnSelf();
  482. $this->order->expects($this->any())
  483. ->method('setStatus')
  484. ->with($newOrderStatus)
  485. ->willReturnSelf();
  486. $this->paymentMethod->expects($this->once())
  487. ->method('getConfigPaymentAction')
  488. ->willReturn(null);
  489. $this->assertEquals($this->payment, $this->payment->place());
  490. $this->assertEquals($sum, $this->payment->getAmountAuthorized());
  491. $this->assertEquals($sum, $this->payment->getBaseAmountAuthorized());
  492. }
  493. /**
  494. * @param bool $isOnline
  495. * @param float $amount
  496. * @dataProvider authorizeDataProvider
  497. */
  498. public function testAuthorize($isOnline, $amount)
  499. {
  500. $this->paymentProcessor->expects($this->once())
  501. ->method('authorize')
  502. ->with($this->payment, $isOnline, $amount)
  503. ->willReturn($this->payment);
  504. $this->assertEquals($this->payment, $this->payment->authorize($isOnline, $amount));
  505. }
  506. /**
  507. * Data rpovider for testAuthorize
  508. * @return array
  509. */
  510. public function authorizeDataProvider()
  511. {
  512. return [
  513. [false, 9.99],
  514. [true, 0.01]
  515. ];
  516. }
  517. public function testAcceptApprovePaymentTrue()
  518. {
  519. $baseGrandTotal = 300.00;
  520. $message = sprintf('Approved the payment online. Transaction ID: "%s"', $this->transactionId);
  521. $acceptPayment = true;
  522. $this->payment->setLastTransId($this->transactionId);
  523. $this->mockInvoice($this->transactionId, 2);
  524. $this->invoice->setBaseGrandTotal($baseGrandTotal);
  525. $this->mockResultTrueMethods($this->transactionId, $baseGrandTotal, $message);
  526. $this->helper->expects($this->once())
  527. ->method('getMethodInstance')
  528. ->will($this->returnValue($this->paymentMethod));
  529. $this->paymentMethod->expects($this->once())
  530. ->method('setStore')
  531. ->will($this->returnSelf());
  532. $this->paymentMethod->expects($this->once())
  533. ->method('acceptPayment')
  534. ->with($this->payment)
  535. ->willReturn($acceptPayment);
  536. $this->payment->accept();
  537. self::assertEquals($baseGrandTotal, $this->payment->getBaseAmountPaidOnline());
  538. }
  539. /**
  540. * @return array
  541. */
  542. public function acceptPaymentFalseProvider()
  543. {
  544. return [
  545. 'Fraud = 1' => [
  546. true,
  547. Order::STATUS_FRAUD
  548. ],
  549. 'Fraud = 0' => [
  550. false,
  551. false
  552. ],
  553. ];
  554. }
  555. /**
  556. * @dataProvider acceptPaymentFalseProvider
  557. * @param bool $isFraudDetected
  558. * @param bool $status
  559. */
  560. public function testAcceptApprovePaymentFalse($isFraudDetected, $status)
  561. {
  562. $message = sprintf('There is no need to approve this payment. Transaction ID: "%s"', $this->transactionId);
  563. $acceptPayment = false;
  564. $orderState = 'random_state';
  565. $this->payment->setLastTransId($this->transactionId);
  566. $this->payment->setData('is_fraud_detected', $isFraudDetected);
  567. $this->order->expects($this->once())
  568. ->method('getState')
  569. ->willReturn($orderState);
  570. $this->assertOrderUpdated(Order::STATE_PAYMENT_REVIEW, $status, $message);
  571. $this->helper->expects($this->once())
  572. ->method('getMethodInstance')
  573. ->will($this->returnValue($this->paymentMethod));
  574. $this->paymentMethod->expects($this->once())
  575. ->method('setStore')
  576. ->will($this->returnSelf());
  577. $this->paymentMethod->expects($this->once())
  578. ->method('acceptPayment')
  579. ->with($this->payment)
  580. ->willReturn($acceptPayment);
  581. $this->payment->accept();
  582. $this->assertEquals($this->transactionId, $this->payment->getLastTransId());
  583. }
  584. /**
  585. *
  586. * @dataProvider acceptPaymentFalseProvider
  587. * @param bool $isFraudDetected
  588. */
  589. public function testAcceptApprovePaymentFalseOrderState($isFraudDetected)
  590. {
  591. $message = sprintf('There is no need to approve this payment. Transaction ID: "%s"', $this->transactionId);
  592. $acceptPayment = false;
  593. $orderState = Order::STATE_PAYMENT_REVIEW;
  594. $this->payment->setLastTransId($this->transactionId);
  595. $this->payment->setData('is_fraud_detected', $isFraudDetected);
  596. $this->order->expects($this->once())
  597. ->method('getState')
  598. ->willReturn($orderState);
  599. $this->order->expects($this->never())
  600. ->method('setState');
  601. $this->order->expects($this->once())
  602. ->method('addStatusHistoryComment')
  603. ->with($message);
  604. $this->helper->expects($this->once())
  605. ->method('getMethodInstance')
  606. ->will($this->returnValue($this->paymentMethod));
  607. $this->paymentMethod->expects($this->once())
  608. ->method('setStore')
  609. ->will($this->returnSelf());
  610. $this->paymentMethod->expects($this->once())
  611. ->method('acceptPayment')
  612. ->with($this->payment)
  613. ->willReturn($acceptPayment);
  614. $this->payment->accept();
  615. $this->assertEquals($this->transactionId, $this->payment->getLastTransId());
  616. }
  617. public function testDenyPaymentFalse()
  618. {
  619. $denyPayment = true;
  620. $message = sprintf('Denied the payment online Transaction ID: "%s"', $this->transactionId);
  621. $this->payment->setLastTransId($this->transactionId);
  622. $this->mockInvoice($this->transactionId);
  623. $this->mockResultFalseMethods($message);
  624. $this->helper->expects($this->once())
  625. ->method('getMethodInstance')
  626. ->will($this->returnValue($this->paymentMethod));
  627. $this->paymentMethod->expects($this->once())
  628. ->method('setStore')
  629. ->will($this->returnSelf());
  630. $this->paymentMethod->expects($this->once())
  631. ->method('denyPayment')
  632. ->with($this->payment)
  633. ->willReturn($denyPayment);
  634. $this->payment->deny();
  635. }
  636. /**
  637. * Test offline IPN calls
  638. */
  639. public function testDenyPaymentIpn()
  640. {
  641. $isOnline = false;
  642. $message = sprintf('Denied the payment online Transaction ID: "%s"', $this->transactionId);
  643. $this->payment->setTransactionId($this->transactionId);
  644. $this->payment->setNotificationResult(true);
  645. $this->mockInvoice($this->transactionId);
  646. $this->mockResultFalseMethods($message);
  647. $this->helper->expects($this->never())
  648. ->method('getMethodInstance');
  649. $this->payment->deny($isOnline);
  650. }
  651. /**
  652. * @dataProvider acceptPaymentFalseProvider
  653. * @param bool $isFraudDetected
  654. * @param bool $status
  655. */
  656. public function testDenyPaymentNegative($isFraudDetected, $status)
  657. {
  658. $denyPayment = false;
  659. $message = sprintf('There is no need to deny this payment. Transaction ID: "%s"', $this->transactionId);
  660. $orderState = 'random_state';
  661. $this->payment->setLastTransId($this->transactionId);
  662. $this->payment->setData('is_fraud_detected', $isFraudDetected);
  663. $this->order->expects($this->once())
  664. ->method('getState')
  665. ->willReturn($orderState);
  666. $this->assertOrderUpdated(Order::STATE_PAYMENT_REVIEW, $status, $message);
  667. $this->helper->expects($this->once())
  668. ->method('getMethodInstance')
  669. ->will($this->returnValue($this->paymentMethod));
  670. $this->paymentMethod->expects($this->once())
  671. ->method('setStore')
  672. ->will($this->returnSelf());
  673. $this->paymentMethod->expects($this->once())
  674. ->method('denyPayment')
  675. ->with($this->payment)
  676. ->willReturn($denyPayment);
  677. $this->payment->deny();
  678. }
  679. public function testDenyPaymentNegativeStateReview()
  680. {
  681. $denyPayment = false;
  682. $message = sprintf('There is no need to deny this payment. Transaction ID: "%s"', $this->transactionId);
  683. $orderState = Order::STATE_PAYMENT_REVIEW;
  684. $this->payment->setLastTransId($this->transactionId);
  685. $this->order->expects($this->once())
  686. ->method('getState')
  687. ->willReturn($orderState);
  688. $this->order->expects($this->never())
  689. ->method('setState');
  690. $this->order->expects($this->once())
  691. ->method('addStatusHistoryComment')
  692. ->with($message);
  693. $this->helper->expects($this->once())
  694. ->method('getMethodInstance')
  695. ->will($this->returnValue($this->paymentMethod));
  696. $this->paymentMethod->expects($this->once())
  697. ->method('setStore')
  698. ->will($this->returnSelf());
  699. $this->paymentMethod->expects($this->once())
  700. ->method('denyPayment')
  701. ->with($this->payment)
  702. ->willReturn($denyPayment);
  703. $this->payment->deny();
  704. }
  705. /**
  706. * Test offline IPN call, negative
  707. */
  708. public function testDenyPaymentIpnNegativeStateReview()
  709. {
  710. $isOnline = false;
  711. $message = sprintf('Registered notification about denied payment. Transaction ID: "%s"', $this->transactionId);
  712. $orderState = Order::STATE_PAYMENT_REVIEW;
  713. $this->payment->setTransactionId($this->transactionId);
  714. $this->payment->setNotificationResult(false);
  715. $this->order->expects($this->once())
  716. ->method('getState')
  717. ->willReturn($orderState);
  718. $this->order->expects($this->never())
  719. ->method('setState');
  720. $this->order->expects($this->once())
  721. ->method('addStatusHistoryComment')
  722. ->with($message);
  723. $this->helper->expects($this->never())
  724. ->method('getMethodInstance')
  725. ->will($this->returnValue($this->paymentMethod));
  726. $this->paymentMethod->expects($this->never())
  727. ->method('setStore')
  728. ->will($this->returnSelf());
  729. $this->paymentMethod->expects($this->never())
  730. ->method('denyPayment')
  731. ->with($this->payment);
  732. $this->payment->deny($isOnline);
  733. }
  734. /**
  735. * @param int $transactionId
  736. * @param int $countCall
  737. */
  738. private function mockInvoice($transactionId, $countCall = 1)
  739. {
  740. $this->invoice->method('getTransactionId')
  741. ->willReturn($transactionId);
  742. $this->invoice->method('load')
  743. ->with($transactionId);
  744. $this->invoice->method('getId')
  745. ->willReturn($transactionId);
  746. $this->order->expects(self::exactly($countCall))
  747. ->method('getInvoiceCollection')
  748. ->willReturn([$this->invoice]);
  749. }
  750. public function testUpdateOnlineTransactionApproved()
  751. {
  752. $message = sprintf('Registered update about approved payment. Transaction ID: "%s"', $this->transactionId);
  753. $storeId = 50;
  754. $baseGrandTotal = 299.99;
  755. $this->payment->setLastTransId($this->transactionId);
  756. $this->payment->setData('is_transaction_approved', true);
  757. $this->mockInvoice($this->transactionId, 2);
  758. $this->invoice->setBaseGrandTotal($baseGrandTotal);
  759. $this->mockResultTrueMethods($this->transactionId, $baseGrandTotal, $message);
  760. $this->order->expects($this->once())
  761. ->method('getStoreId')
  762. ->willReturn($storeId);
  763. $this->helper->expects($this->once())
  764. ->method('getMethodInstance')
  765. ->will($this->returnValue($this->paymentMethod));
  766. $this->paymentMethod->expects($this->once())
  767. ->method('setStore')
  768. ->with($storeId)
  769. ->willReturn($this->paymentMethod);
  770. $this->paymentMethod->expects($this->once())
  771. ->method('fetchTransactionInfo')
  772. ->with($this->payment, $this->transactionId);
  773. $this->payment->update();
  774. $this->assertEquals($baseGrandTotal, $this->payment->getBaseAmountPaidOnline());
  775. }
  776. /**
  777. * Test update calls from IPN controller
  778. */
  779. public function testUpdateOnlineTransactionApprovedIpn()
  780. {
  781. $isOnline = false;
  782. $message = sprintf('Registered update about approved payment. Transaction ID: "%s"', $this->transactionId);
  783. $baseGrandTotal = 299.99;
  784. $this->payment->setTransactionId($this->transactionId);
  785. $this->payment->setData('is_transaction_approved', true);
  786. $this->mockInvoice($this->transactionId, 2);
  787. $this->invoice->setBaseGrandTotal($baseGrandTotal);
  788. $this->mockResultTrueMethods($this->transactionId, $baseGrandTotal, $message);
  789. $this->order->expects(self::never())
  790. ->method('getStoreId');
  791. $this->helper->expects(self::never())
  792. ->method('getMethodInstance');
  793. $this->paymentMethod->expects(self::never())
  794. ->method('setStore');
  795. $this->paymentMethod->expects(self::never())
  796. ->method('fetchTransactionInfo');
  797. $this->payment->update($isOnline);
  798. $this->assertEquals($baseGrandTotal, $this->payment->getBaseAmountPaidOnline());
  799. }
  800. public function testUpdateOnlineTransactionDenied()
  801. {
  802. $message = sprintf('Registered update about denied payment. Transaction ID: "%s"', $this->transactionId);
  803. $storeId = 50;
  804. $this->payment->setLastTransId($this->transactionId);
  805. $this->payment->setData('is_transaction_denied', true);
  806. $this->mockInvoice($this->transactionId);
  807. $this->mockResultFalseMethods($message);
  808. $this->order->expects($this->once())
  809. ->method('getStoreId')
  810. ->willReturn($storeId);
  811. $this->helper->expects($this->once())
  812. ->method('getMethodInstance')
  813. ->will($this->returnValue($this->paymentMethod));
  814. $this->paymentMethod->expects($this->once())
  815. ->method('setStore')
  816. ->with($storeId)
  817. ->willReturn($this->paymentMethod);
  818. $this->paymentMethod->expects($this->once())
  819. ->method('fetchTransactionInfo')
  820. ->with($this->payment, $this->transactionId);
  821. $this->payment->update();
  822. }
  823. /**
  824. * @dataProvider acceptPaymentFalseProvider
  825. * @param bool $isFraudDetected
  826. * @param bool $status
  827. */
  828. public function testUpdateOnlineTransactionDeniedFalse($isFraudDetected, $status)
  829. {
  830. $message = sprintf('There is no update for the payment. Transaction ID: "%s"', $this->transactionId);
  831. $storeId = 50;
  832. $orderState = 'random_state';
  833. $this->payment->setLastTransId($this->transactionId);
  834. $this->payment->setData('is_transaction_denied', false);
  835. $this->payment->setData('is_transaction_approved', false);
  836. $this->payment->setData('is_fraud_detected', $isFraudDetected);
  837. $this->mockInvoice($this->transactionId);
  838. $this->order->expects($this->once())
  839. ->method('getState')
  840. ->willReturn($orderState);
  841. $this->assertOrderUpdated(Order::STATE_PAYMENT_REVIEW, $status, $message);
  842. $this->order->expects($this->once())
  843. ->method('getStoreId')
  844. ->willReturn($storeId);
  845. $this->helper->expects($this->once())
  846. ->method('getMethodInstance')
  847. ->will($this->returnValue($this->paymentMethod));
  848. $this->paymentMethod->expects($this->once())
  849. ->method('setStore')
  850. ->with($storeId)
  851. ->willReturn($this->paymentMethod);
  852. $this->paymentMethod->expects($this->once())
  853. ->method('fetchTransactionInfo')
  854. ->with($this->payment, $this->transactionId);
  855. $this->payment->update();
  856. $this->assertEquals($this->transactionId, $this->payment->getLastTransId());
  857. }
  858. public function testUpdateOnlineTransactionDeniedFalseHistoryComment()
  859. {
  860. $message = sprintf('There is no update for the payment. Transaction ID: "%s"', $this->transactionId);
  861. $storeId = 50;
  862. $orderState = Order::STATE_PAYMENT_REVIEW;
  863. $this->payment->setLastTransId($this->transactionId);
  864. $this->payment->setData('is_transaction_denied', false);
  865. $this->payment->setData('is_transaction_approved', false);
  866. $this->mockInvoice($this->transactionId);
  867. $this->order->expects($this->once())
  868. ->method('getState')
  869. ->willReturn($orderState);
  870. $this->order->expects($this->never())
  871. ->method('setState');
  872. $this->order->expects($this->once())
  873. ->method('addStatusHistoryComment')
  874. ->with($message);
  875. $this->order->expects($this->once())
  876. ->method('getStoreId')
  877. ->willReturn($storeId);
  878. $this->helper->expects($this->once())
  879. ->method('getMethodInstance')
  880. ->will($this->returnValue($this->paymentMethod));
  881. $this->paymentMethod->expects($this->once())
  882. ->method('setStore')
  883. ->with($storeId)
  884. ->willReturn($this->paymentMethod);
  885. $this->paymentMethod->expects($this->once())
  886. ->method('fetchTransactionInfo')
  887. ->with($this->payment, $this->transactionId);
  888. $this->payment->update();
  889. $this->assertEquals($this->transactionId, $this->payment->getLastTransId());
  890. }
  891. /**
  892. * @param int $transactionId
  893. * @param float $baseGrandTotal
  894. * @param string $message
  895. */
  896. protected function mockResultTrueMethods($transactionId, $baseGrandTotal, $message)
  897. {
  898. $status = 'status';
  899. $this->invoice->expects($this->once())
  900. ->method('pay')
  901. ->willReturn($transactionId);
  902. $this->invoice->method('getBaseGrandTotal')
  903. ->willReturn($baseGrandTotal);
  904. //acceptPayment = true
  905. $this->order->expects($this->once())
  906. ->method('addRelatedObject')
  907. ->with($this->invoice);
  908. $this->mockGetDefaultStatus(Order::STATE_PROCESSING, $status);
  909. $this->assertOrderUpdated(Order::STATE_PROCESSING, $status, $message);
  910. }
  911. /**
  912. * @param $message
  913. */
  914. protected function mockResultFalseMethods($message)
  915. {
  916. $this->invoice->expects($this->once())
  917. ->method('cancel');
  918. $this->order->expects($this->once())
  919. ->method('addRelatedObject')
  920. ->with($this->invoice);
  921. $this->order->expects($this->once())
  922. ->method('registerCancellation')
  923. ->with($message, false);
  924. }
  925. public function testAcceptWithoutInvoiceResultTrue()
  926. {
  927. $baseGrandTotal = null;
  928. $acceptPayment = true;
  929. $this->payment->setData('transaction_id', $this->transactionId);
  930. $this->invoice->expects($this->never())
  931. ->method('pay');
  932. $this->order->expects($this->any())
  933. ->method('getInvoiceCollection')
  934. ->willReturn([]);
  935. $this->helper->expects($this->once())
  936. ->method('getMethodInstance')
  937. ->will($this->returnValue($this->paymentMethod));
  938. $this->paymentMethod->expects($this->once())
  939. ->method('setStore')
  940. ->will($this->returnSelf());
  941. $this->paymentMethod->expects($this->once())
  942. ->method('acceptPayment')
  943. ->with($this->payment)
  944. ->willReturn($acceptPayment);
  945. $status = 'status';
  946. $this->mockGetDefaultStatus(Order::STATE_PROCESSING, $status);
  947. $this->assertOrderUpdated(Order::STATE_PROCESSING, $status, __('Approved the payment online.'));
  948. $this->payment->accept();
  949. $this->assertEquals($baseGrandTotal, $this->payment->getBaseAmountPaidOnline());
  950. }
  951. public function testDenyWithoutInvoiceResultFalse()
  952. {
  953. $baseGrandTotal = null;
  954. $denyPayment = true;
  955. $this->payment->setData('transaction_id', $this->transactionId);
  956. $this->invoice->expects($this->never())
  957. ->method('cancel');
  958. $this->order->expects($this->any())
  959. ->method('getInvoiceCollection')
  960. ->willReturn([]);
  961. $this->helper->expects($this->once())
  962. ->method('getMethodInstance')
  963. ->will($this->returnValue($this->paymentMethod));
  964. $this->paymentMethod->expects($this->once())
  965. ->method('setStore')
  966. ->will($this->returnSelf());
  967. $this->paymentMethod->expects($this->once())
  968. ->method('denyPayment')
  969. ->with($this->payment)
  970. ->willReturn($denyPayment);
  971. $status = 'status';
  972. $this->mockGetDefaultStatus(Order::STATE_PROCESSING, $status);
  973. $this->assertOrderUpdated(Order::STATE_PROCESSING, $status, __('Denied the payment online'));
  974. $this->payment->deny();
  975. $this->assertEquals($baseGrandTotal, $this->payment->getBaseAmountPaidOnline());
  976. }
  977. public function testCanCaptureNoAuthorizationTransaction()
  978. {
  979. $this->paymentMethod->expects($this->once())
  980. ->method('canCapture')
  981. ->willReturn(true);
  982. $this->assertTrue($this->payment->canCapture());
  983. }
  984. public function testCanCaptureCreateTransaction()
  985. {
  986. $this->paymentMethod->expects($this->once())
  987. ->method('canCapture')
  988. ->willReturn(true);
  989. $parentTransactionId = 1;
  990. $paymentId = 22;
  991. $this->payment->setId($paymentId);
  992. $this->payment->setParentTransactionId($parentTransactionId);
  993. $transaction = $this->createMock(\Magento\Sales\Model\Order\Payment\Transaction::class);
  994. $transaction->expects($this->once())
  995. ->method('getIsClosed')
  996. ->willReturn(false);
  997. $this->transactionManagerMock->expects($this->once())
  998. ->method('getAuthorizationTransaction')
  999. ->with($parentTransactionId, $paymentId)
  1000. ->willReturn($transaction);
  1001. $this->assertTrue($this->payment->canCapture());
  1002. }
  1003. public function testCanCaptureAuthorizationTransaction()
  1004. {
  1005. $paymentId = 1;
  1006. $parentTransactionId = 1;
  1007. $this->payment->setParentTransactionId($parentTransactionId);
  1008. $this->payment->setId($paymentId);
  1009. $this->paymentMethod->expects($this->once())
  1010. ->method('canCapture')
  1011. ->willReturn(true);
  1012. $transaction = $this->createMock(\Magento\Sales\Model\Order\Payment\Transaction::class);
  1013. $this->transactionManagerMock->expects($this->once())
  1014. ->method('getAuthorizationTransaction')
  1015. ->with($parentTransactionId, $paymentId)
  1016. ->willReturn($transaction);
  1017. $transaction->expects($this->once())->method('getIsClosed')->willReturn(true);
  1018. $this->transactionRepositoryMock->expects($this->once())
  1019. ->method('getByTransactionType')
  1020. ->with(Transaction::TYPE_ORDER, $paymentId)
  1021. ->willReturn($transaction);
  1022. $this->assertTrue($this->payment->canCapture());
  1023. }
  1024. public function testCannotCapture()
  1025. {
  1026. $this->paymentMethod->expects($this->once())->method('canCapture')->willReturn(false);
  1027. $this->assertFalse($this->payment->canCapture());
  1028. }
  1029. /**
  1030. * Tests pay method and perform assertions for payment amount
  1031. */
  1032. public function testPay()
  1033. {
  1034. $amountPaid = 10;
  1035. $shippingCaptured = 5;
  1036. self::assertNull($this->payment->getAmountPaid());
  1037. $this->mockInvoice(null);
  1038. $this->invoice->setGrandTotal($amountPaid);
  1039. $this->invoice->setBaseGrandTotal($amountPaid);
  1040. $this->invoice->setShippingAmount($shippingCaptured);
  1041. $this->invoice->setBaseShippingAmount($shippingCaptured);
  1042. self::assertSame($this->payment, $this->payment->pay($this->invoice));
  1043. self::assertEquals($amountPaid, $this->payment->getAmountPaid());
  1044. self::assertEquals($amountPaid, $this->payment->getBaseAmountPaid());
  1045. self::assertEquals($shippingCaptured, $this->payment->getShippingCaptured());
  1046. self::assertEquals($shippingCaptured, $this->payment->getBaseShippingCaptured());
  1047. }
  1048. /**
  1049. * Checks if total paid amount correctly calculated for multiple order invoices.
  1050. */
  1051. public function testPayWithMultipleInvoices()
  1052. {
  1053. $this->invoice->setGrandTotal(5);
  1054. $this->invoice->setShippingAmount(5);
  1055. /** @var Invoice|MockObject $invoice */
  1056. $invoice = $this->getMockBuilder(Invoice::class)
  1057. ->disableOriginalConstructor()
  1058. ->setMethods(['getGrandTotal'])
  1059. ->getMock();
  1060. $invoice->setGrandTotal(5);
  1061. $this->order->method('getInvoiceCollection')
  1062. ->willReturn([$this->invoice, $invoice]);
  1063. $this->payment->pay($this->invoice);
  1064. self::assertEquals(10, $this->payment->getAmountPaid());
  1065. self::assertEquals(5, $this->payment->getShippingCaptured());
  1066. }
  1067. public function testGetOrder()
  1068. {
  1069. $payment = $this->initPayment();
  1070. $this->orderRepository->expects($this->once())->method('get')->willReturn($this->order);
  1071. $payment->setParentId(1211);
  1072. $this->assertSame($this->order, $payment->getOrder());
  1073. }
  1074. public function testGetOrderDefault()
  1075. {
  1076. $this->orderRepository->expects($this->never())->method('get');
  1077. $this->assertSame($this->order, $this->payment->getOrder());
  1078. }
  1079. public function testGetOrderNull()
  1080. {
  1081. $payment = $this->initPayment();
  1082. $this->orderRepository->expects($this->never())->method('get');
  1083. $this->assertNull($payment->getOrder());
  1084. }
  1085. public function testCancelInvoice()
  1086. {
  1087. $expects = [
  1088. 'amount_paid' => 10,
  1089. 'base_amount_paid' => 10,
  1090. 'shipping_captured' => 5,
  1091. 'base_shipping_captured' => 5,
  1092. ];
  1093. $this->assertNull($this->payment->getData('amount_paid'));
  1094. $this->invoice->expects($this->once())->method('getGrandTotal')->willReturn($expects['amount_paid']);
  1095. $this->invoice->expects($this->once())->method('getBaseGrandTotal')->willReturn(
  1096. $expects['base_amount_paid']
  1097. );
  1098. $this->invoice->expects($this->once())->method('getShippingAmount')->willReturn(
  1099. $expects['shipping_captured']
  1100. );
  1101. $this->invoice->expects($this->once())->method('getBaseShippingAmount')->willReturn(
  1102. $expects['base_shipping_captured']
  1103. );
  1104. $this->eventManagerMock->expects($this->once())->method('dispatch')->with(
  1105. 'sales_order_payment_cancel_invoice',
  1106. ['payment' => $this->payment, 'invoice' => $this->invoice]
  1107. );
  1108. $this->assertSame($this->payment, $this->payment->cancelInvoice($this->invoice));
  1109. $this->assertEquals(-1 * $expects['amount_paid'], $this->payment->getData('amount_paid'));
  1110. $this->assertEquals(-1 * $expects['base_amount_paid'], $this->payment->getData('base_amount_paid'));
  1111. $this->assertEquals(-1 * $expects['shipping_captured'], $this->payment->getData('shipping_captured'));
  1112. $this->assertEquals(
  1113. -1 * $expects['base_shipping_captured'],
  1114. $this->payment->getData('base_shipping_captured')
  1115. );
  1116. }
  1117. public function testRegisterRefundNotificationTransactionExists()
  1118. {
  1119. $amount = 10;
  1120. $paymentId = 1;
  1121. $orderId = 9;
  1122. $this->payment->setParentTransactionId($this->transactionId);
  1123. $this->payment->setId($paymentId);
  1124. $this->order->setId($orderId);
  1125. $transaction = $this->createMock(\Magento\Sales\Model\ResourceModel\Order\Payment\Transaction::class);
  1126. $newTransactionId = $this->transactionId . '-' . Transaction::TYPE_REFUND;
  1127. $this->transactionRepositoryMock->expects($this->once())
  1128. ->method('getByTransactionId')
  1129. ->with($this->transactionId)
  1130. ->willReturn($transaction);
  1131. $this->transactionManagerMock->expects($this->once())
  1132. ->method('isTransactionExists')
  1133. ->with($newTransactionId, $paymentId, $orderId)
  1134. ->willReturn(true);
  1135. $this->transactionManagerMock->expects($this->once())
  1136. ->method('generateTransactionId')
  1137. ->with($this->payment, Transaction::TYPE_REFUND, $transaction)
  1138. ->willReturn($newTransactionId);
  1139. $this->assertSame($this->payment, $this->payment->registerRefundNotification($amount));
  1140. }
  1141. /**
  1142. * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
  1143. */
  1144. public function testRegisterRefundNotification()
  1145. {
  1146. $message = 'Registered notification about refunded amount of . Transaction ID: "' .
  1147. self::TRANSACTION_ID . '-refund"';
  1148. $amount = 50;
  1149. $grandTotalCreditMemo = 50;
  1150. $invoiceBaseGrandTotal = 50;
  1151. $invoiceBaseTotalRefunded = 0;
  1152. $this->invoice->expects($this->any())->method('getBaseGrandTotal')->willReturn($invoiceBaseGrandTotal);
  1153. $this->invoice->expects($this->any())->method('getBaseTotalRefunded')->willReturn(
  1154. $invoiceBaseTotalRefunded
  1155. );
  1156. $this->creditMemoMock->expects($this->any())->method('getGrandTotal')->willReturn($grandTotalCreditMemo);
  1157. $this->payment->setParentTransactionId($this->transactionId);
  1158. $this->mockInvoice($this->transactionId, 1);
  1159. $this->creditmemoFactoryMock->expects($this->once())
  1160. ->method('createByInvoice')
  1161. ->with($this->invoice, ['adjustment_negative' => $invoiceBaseGrandTotal - $amount])
  1162. ->willReturn($this->creditMemoMock);
  1163. $this->creditMemoMock->expects($this->once())->method('setPaymentRefundDisallowed')->willReturnSelf();
  1164. $this->creditMemoMock->expects($this->once())->method('setAutomaticallyCreated')->willReturnSelf();
  1165. $this->creditMemoMock->expects($this->once())->method('addComment')->willReturnSelf();
  1166. $this->creditmemoManagerMock->expects($this->once())
  1167. ->method('refund')
  1168. ->with($this->creditMemoMock, false)
  1169. ->willReturn($this->creditMemoMock);
  1170. $this->order->expects($this->once())->method('getBaseCurrency')->willReturn($this->currencyMock);
  1171. $parentTransaction = $this->createPartialMock(
  1172. \Magento\Sales\Model\Order\Payment\Transaction::class,
  1173. ['setOrderId', 'setPaymentId', 'loadByTxnId', 'getId', 'getTxnId', 'setTxnId', 'getTxnType']
  1174. );
  1175. $newTransactionId = $this->transactionId . '-' . Transaction::TYPE_REFUND;
  1176. $this->transactionRepositoryMock->expects($this->once())
  1177. ->method('getByTransactionId')
  1178. ->with($this->transactionId)
  1179. ->willReturn($parentTransaction);
  1180. $this->transactionManagerMock->expects($this->once())
  1181. ->method('isTransactionExists')
  1182. ->with($newTransactionId)
  1183. ->willReturn(false);
  1184. $this->transactionManagerMock->expects($this->once())
  1185. ->method('generateTransactionId')
  1186. ->with($this->payment, Transaction::TYPE_REFUND, $parentTransaction)
  1187. ->willReturn($newTransactionId);
  1188. $status = 'status';
  1189. $this->mockGetDefaultStatus(Order::STATE_PROCESSING, $status);
  1190. $this->assertOrderUpdated(Order::STATE_PROCESSING, $status, $message);
  1191. $additionalInformation = [];
  1192. $failSafe = false;
  1193. $transactionType = Transaction::TYPE_REFUND;
  1194. $this->getTransactionBuilderMock(
  1195. $additionalInformation,
  1196. $failSafe,
  1197. $transactionType,
  1198. $this->transactionId . '-' . Transaction::TYPE_REFUND
  1199. );
  1200. $this->assertSame($this->payment, $this->payment->registerRefundNotification($amount));
  1201. $this->assertSame($this->creditMemoMock, $this->payment->getData('created_creditmemo'));
  1202. $this->assertEquals($grandTotalCreditMemo, $this->payment->getData('amount_refunded'));
  1203. }
  1204. public function testRegisterRefundNotificationWrongAmount()
  1205. {
  1206. $amount = 30;
  1207. $grandTotalCreditMemo = 50;
  1208. $invoiceBaseGrandTotal = 50;
  1209. $invoiceBaseTotalRefunded = 0;
  1210. $this->invoice->expects($this->any())->method('getBaseGrandTotal')->willReturn($invoiceBaseGrandTotal);
  1211. $this->invoice->expects($this->any())->method('getBaseTotalRefunded')->willReturn(
  1212. $invoiceBaseTotalRefunded
  1213. );
  1214. $this->creditMemoMock->expects($this->any())->method('getGrandTotal')->willReturn($grandTotalCreditMemo);
  1215. $this->payment->setParentTransactionId($this->transactionId);
  1216. $this->mockInvoice($this->transactionId, 1);
  1217. $this->order->expects($this->once())->method('getBaseCurrency')->willReturn($this->currencyMock);
  1218. $parentTransaction = $this->createPartialMock(
  1219. \Magento\Sales\Model\Order\Payment\Transaction::class,
  1220. ['setOrderId', 'setPaymentId', 'loadByTxnId', 'getId', 'getTxnId', 'getTxnType']
  1221. );
  1222. //generate new transaction and check if not exists
  1223. $this->transactionRepositoryMock->expects($this->once())
  1224. ->method('getByTransactionId')
  1225. ->with($this->transactionId)
  1226. ->willReturn($parentTransaction);
  1227. $newTransactionId = $this->transactionId . '-refund';
  1228. $this->transactionManagerMock->expects($this->once())
  1229. ->method('isTransactionExists')
  1230. ->with($newTransactionId)
  1231. ->willReturn(false);
  1232. $this->transactionManagerMock->expects($this->once())
  1233. ->method('generateTransactionId')
  1234. ->with($this->payment, Transaction::TYPE_REFUND, $parentTransaction)
  1235. ->willReturn($newTransactionId);
  1236. $this->assertSame($this->payment, $this->payment->registerRefundNotification($amount));
  1237. }
  1238. /**
  1239. * @dataProvider boolProvider
  1240. */
  1241. public function testCanRefund($canRefund)
  1242. {
  1243. $this->paymentMethod->expects($this->once())
  1244. ->method('canRefund')
  1245. ->willReturn($canRefund);
  1246. $this->assertEquals($canRefund, $this->payment->canRefund());
  1247. }
  1248. /**
  1249. * @covers \Magento\Sales\Model\Order\Payment::refund()
  1250. */
  1251. public function testRefund()
  1252. {
  1253. $amount = 204.04;
  1254. $this->creditMemoMock->expects(static::once())
  1255. ->method('getBaseGrandTotal')
  1256. ->willReturn($amount);
  1257. $this->creditMemoMock->expects(static::once())
  1258. ->method('getGrandTotal')
  1259. ->willReturn($amount);
  1260. $this->creditMemoMock->expects(static::once())
  1261. ->method('getDoTransaction')
  1262. ->willReturn(true);
  1263. $this->paymentMethod->expects(static::once())
  1264. ->method('canRefund')
  1265. ->willReturn(true);
  1266. $this->mockInvoice(self::TRANSACTION_ID, 0);
  1267. $this->creditMemoMock->expects(static::once())
  1268. ->method('getInvoice')
  1269. ->willReturn($this->invoice);
  1270. $this->creditMemoMock->expects(static::once())
  1271. ->method('getOrder')
  1272. ->willReturn($this->order);
  1273. $captureTranId = self::TRANSACTION_ID . '-' . Transaction::TYPE_CAPTURE;
  1274. $captureTransaction = $this->getMockBuilder(Transaction::class)
  1275. ->disableOriginalConstructor()
  1276. ->setMethods(['getTxnId'])
  1277. ->getMock();
  1278. $refundTranId = $captureTranId . '-' . Transaction::TYPE_REFUND;
  1279. $this->transactionManagerMock->expects(static::once())
  1280. ->method('generateTransactionId')
  1281. ->willReturn($refundTranId);
  1282. $captureTransaction->expects(static::once())
  1283. ->method('getTxnId')
  1284. ->willReturn($captureTranId);
  1285. $this->transactionRepositoryMock->expects(static::once())
  1286. ->method('getByTransactionId')
  1287. ->willReturn($captureTransaction);
  1288. $this->paymentMethod->expects(static::once())
  1289. ->method('refund')
  1290. ->with($this->payment, $amount);
  1291. $isOnline = true;
  1292. $this->getTransactionBuilderMock([], $isOnline, Transaction::TYPE_REFUND, $refundTranId);
  1293. $this->currencyMock->expects(static::once())
  1294. ->method('formatTxt')
  1295. ->willReturn($amount);
  1296. $this->order->expects(static::once())
  1297. ->method('getBaseCurrency')
  1298. ->willReturn($this->currencyMock);
  1299. $status = 'status';
  1300. $message = 'We refunded ' . $amount . ' online. Transaction ID: "' . $refundTranId . '"';
  1301. $this->orderStateResolver->expects($this->once())->method('getStateForOrder')
  1302. ->with($this->order)
  1303. ->willReturn(Order::STATE_CLOSED);
  1304. $this->mockGetDefaultStatus(Order::STATE_CLOSED, $status);
  1305. $this->assertOrderUpdated(Order::STATE_PROCESSING, $status, $message);
  1306. static::assertSame($this->payment, $this->payment->refund($this->creditMemoMock));
  1307. static::assertEquals($amount, $this->payment->getData('amount_refunded'));
  1308. static::assertEquals($amount, $this->payment->getData('base_amount_refunded_online'));
  1309. static::assertEquals($amount, $this->payment->getData('base_amount_refunded'));
  1310. }
  1311. /**
  1312. * @return array
  1313. */
  1314. public function boolProvider()
  1315. {
  1316. return [
  1317. [true],
  1318. [false]
  1319. ];
  1320. }
  1321. /**
  1322. * @covers \Magento\Sales\Model\Order\Payment::isCaptureFinal()
  1323. * @return void
  1324. */
  1325. public function testIsCaptureFinal()
  1326. {
  1327. $amount = 23.02;
  1328. $partialAmount = 12.00;
  1329. $this->order->expects(static::exactly(2))
  1330. ->method('getBaseTotalDue')
  1331. ->willReturn($amount);
  1332. static::assertFalse($this->payment->isCaptureFinal($partialAmount));
  1333. static::assertTrue($this->payment->isCaptureFinal($amount));
  1334. }
  1335. /**
  1336. * @covers \Magento\Sales\Model\Order\Payment::getShouldCloseParentTransaction()
  1337. * @return void
  1338. */
  1339. public function testGetShouldCloseParentTransaction()
  1340. {
  1341. $this->payment->setShouldCloseParentTransaction(1);
  1342. static::assertTrue($this->payment->getShouldCloseParentTransaction());
  1343. $this->payment->setShouldCloseParentTransaction(0);
  1344. static::assertFalse($this->payment->getShouldCloseParentTransaction());
  1345. }
  1346. /**
  1347. * @return object
  1348. */
  1349. protected function initPayment()
  1350. {
  1351. return (new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this))->getObject(
  1352. \Magento\Sales\Model\Order\Payment::class,
  1353. [
  1354. 'context' => $this->context,
  1355. 'creditmemoFactory' => $this->creditmemoFactoryMock,
  1356. 'paymentData' => $this->helper,
  1357. 'priceCurrency' => $this->priceCurrencyMock,
  1358. 'transactionRepository' => $this->transactionRepositoryMock,
  1359. 'transactionManager' => $this->transactionManagerMock,
  1360. 'transactionBuilder' => $this->transactionBuilderMock,
  1361. 'paymentProcessor' => $this->paymentProcessor,
  1362. 'orderRepository' => $this->orderRepository,
  1363. 'creditmemoManager' => $this->creditmemoManagerMock
  1364. ]
  1365. );
  1366. }
  1367. /**
  1368. * @param $state
  1369. * @param null $status
  1370. * @param null $message
  1371. * @param null $isCustomerNotified
  1372. */
  1373. protected function assertOrderUpdated(
  1374. $state,
  1375. $status = null,
  1376. $message = null,
  1377. $isCustomerNotified = null
  1378. ) {
  1379. $this->order->expects($this->any())
  1380. ->method('setState')
  1381. ->with($state)
  1382. ->willReturnSelf();
  1383. $this->order->expects($this->any())
  1384. ->method('setStatus')
  1385. ->with($status)
  1386. ->willReturnSelf();
  1387. $statusHistory = $this->getMockForAbstractClass(
  1388. \Magento\Sales\Api\Data\OrderStatusHistoryInterface::class
  1389. );
  1390. $this->order->expects($this->any())
  1391. ->method('addStatusHistoryComment')
  1392. ->with($message)
  1393. ->willReturn($statusHistory);
  1394. $this->order->expects($this->any())
  1395. ->method('setIsCustomerNotified')
  1396. ->with($isCustomerNotified)
  1397. ->willReturn($statusHistory);
  1398. }
  1399. /**
  1400. * @param $state
  1401. * @param $status
  1402. * @param array $allStatuses
  1403. */
  1404. protected function mockGetDefaultStatus($state, $status, $allStatuses = [])
  1405. {
  1406. /** @var \Magento\Sales\Model\Order\Config | \PHPUnit_Framework_MockObject_MockObject $orderConfigMock */
  1407. $orderConfigMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Config::class)
  1408. ->disableOriginalConstructor()
  1409. ->setMethods(['getStateStatuses', 'getStateDefaultStatus'])
  1410. ->getMock();
  1411. if (!empty($allStatuses)) {
  1412. $orderConfigMock->expects($this->any())
  1413. ->method('getStateStatuses')
  1414. ->with($state)
  1415. ->will($this->returnValue($allStatuses));
  1416. }
  1417. $orderConfigMock->expects($this->any())
  1418. ->method('getStateDefaultStatus')
  1419. ->with($state)
  1420. ->will($this->returnValue($status));
  1421. $this->order->expects($this->any())
  1422. ->method('getConfig')
  1423. ->will($this->returnValue($orderConfigMock));
  1424. }
  1425. /**
  1426. * @param $transactionId
  1427. * @return MockObject
  1428. */
  1429. protected function getTransactionMock($transactionId)
  1430. {
  1431. $transaction = $this->createPartialMock(\Magento\Sales\Model\Order\Payment\Transaction::class, [
  1432. 'getId',
  1433. 'setOrderId',
  1434. 'setPaymentId',
  1435. 'loadByTxnId',
  1436. 'setTxnId',
  1437. 'getTransactionId',
  1438. 'setTxnType',
  1439. 'isFailsafe',
  1440. 'getTxnId',
  1441. 'getHtmlTxnId',
  1442. 'getTxnType'
  1443. ]);
  1444. $transaction->expects($this->any())->method('getId')->willReturn($transactionId);
  1445. $transaction->expects($this->any())->method('getTxnId')->willReturn($transactionId);
  1446. $transaction->expects($this->any())->method('getHtmlTxnId')->willReturn($transactionId);
  1447. return $transaction;
  1448. }
  1449. /**
  1450. * @param $additionalInformation
  1451. * @param $failSafe
  1452. * @param $transactionType
  1453. * @param bool $transactionId
  1454. */
  1455. protected function getTransactionBuilderMock(
  1456. $additionalInformation,
  1457. $failSafe,
  1458. $transactionType,
  1459. $transactionId = false
  1460. ) {
  1461. if (!$transactionId) {
  1462. $transactionId = $this->transactionId;
  1463. }
  1464. $this->transactionBuilderMock->expects($this->once())
  1465. ->method('setPayment')
  1466. ->with($this->payment)
  1467. ->willReturnSelf();
  1468. $this->transactionBuilderMock->expects($this->once())
  1469. ->method('setOrder')
  1470. ->with($this->order)
  1471. ->willReturnSelf();
  1472. $this->transactionBuilderMock->expects($this->once())
  1473. ->method('setTransactionId')
  1474. ->with($transactionId)
  1475. ->willReturnSelf();
  1476. $this->transactionBuilderMock->expects($this->once())
  1477. ->method('setAdditionalInformation')
  1478. ->with($additionalInformation)
  1479. ->willReturnSelf();
  1480. $this->transactionBuilderMock->expects($this->once())
  1481. ->method('setFailSafe')
  1482. ->with($failSafe)
  1483. ->willReturnSelf();
  1484. $transaction = $this->getTransactionMock($transactionId);
  1485. $this->transactionBuilderMock->expects($this->once())
  1486. ->method('build')
  1487. ->with($transactionType)
  1488. ->willReturn($transaction);
  1489. }
  1490. /**
  1491. * @return string
  1492. */
  1493. protected function getTransactionIdComment()
  1494. {
  1495. return __(' Transaction ID: "%1"', $this->transactionId);
  1496. }
  1497. }