Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
DirectpostTest.php
Go to the documentation of this file.
1 <?php
7 
17 
22 class DirectpostTest extends \PHPUnit\Framework\TestCase
23 {
24  const TOTAL_AMOUNT = 100.02;
25  const INVOICE_NUM = '00000001';
26  const TRANSACTION_ID = '41a23x34fd124';
27 
31  protected $directpost;
32 
36  protected $scopeConfigMock;
37 
41  protected $paymentMock;
42 
46  protected $dataHelperMock;
47 
52 
57 
61  protected $responseMock;
62 
67 
71  protected $httpClientMock;
72 
76  protected $requestFactory;
77 
81  private $paymentFailures;
82 
86  protected function setUp()
87  {
88  $this->scopeConfigMock = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class)
89  ->getMock();
90  $this->paymentMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Payment::class)
91  ->disableOriginalConstructor()
92  ->setMethods([
93  'getOrder', 'getId', 'setAdditionalInformation', 'getAdditionalInformation',
94  'setIsTransactionDenied', 'setIsTransactionClosed', 'decrypt', 'getCcLast4',
95  'getParentTransactionId', 'getPoNumber'
96  ])
97  ->getMock();
98  $this->dataHelperMock = $this->getMockBuilder(\Magento\Authorizenet\Helper\Data::class)
99  ->disableOriginalConstructor()
100  ->getMock();
101 
102  $this->initResponseFactoryMock();
103 
104  $this->transactionRepositoryMock = $this->getMockBuilder(
105  \Magento\Sales\Model\Order\Payment\Transaction\Repository::class
106  )
107  ->disableOriginalConstructor()
108  ->setMethods(['getByTransactionId'])
109  ->getMock();
110 
111  $this->transactionServiceMock = $this->getMockBuilder(\Magento\Authorizenet\Model\TransactionService::class)
112  ->disableOriginalConstructor()
113  ->setMethods(['getTransactionDetails'])
114  ->getMock();
115 
116  $this->paymentFailures = $this->getMockBuilder(
117  PaymentFailuresInterface::class
118  )
119  ->disableOriginalConstructor()
120  ->getMock();
121 
122  $this->requestFactory = $this->getRequestFactoryMock();
123  $httpClientFactoryMock = $this->getHttpClientFactoryMock();
124 
125  $helper = new ObjectManagerHelper($this);
126  $this->directpost = $helper->getObject(
127  \Magento\Authorizenet\Model\Directpost::class,
128  [
129  'scopeConfig' => $this->scopeConfigMock,
130  'dataHelper' => $this->dataHelperMock,
131  'requestFactory' => $this->requestFactory,
132  'responseFactory' => $this->responseFactoryMock,
133  'transactionRepository' => $this->transactionRepositoryMock,
134  'transactionService' => $this->transactionServiceMock,
135  'httpClientFactory' => $httpClientFactoryMock,
136  'paymentFailures' => $this->paymentFailures,
137  ]
138  );
139  }
140 
141  public function testGetConfigInterface()
142  {
143  $this->assertInstanceOf(
144  \Magento\Payment\Model\Method\ConfigInterface::class,
145  $this->directpost->getConfigInterface()
146  );
147  }
148 
149  public function testGetConfigValue()
150  {
151  $field = 'some_field';
152  $returnValue = 'expected';
153  $this->scopeConfigMock->expects($this->once())
154  ->method('getValue')
155  ->with('payment/authorizenet_directpost/' . $field)
156  ->willReturn($returnValue);
157  $this->assertEquals($returnValue, $this->directpost->getValue($field));
158  }
159 
160  public function testSetDataHelper()
161  {
162  $storeId = 'store-id';
163  $expectedResult = 'relay-url';
164 
165  $helperDataMock = $this->getMockBuilder(\Magento\Authorizenet\Helper\Backend\Data::class)
166  ->disableOriginalConstructor()
167  ->getMock();
168 
169  $helperDataMock->expects($this->once())
170  ->method('getRelayUrl')
171  ->with($storeId)
172  ->willReturn($expectedResult);
173 
174  $this->directpost->setDataHelper($helperDataMock);
175  $this->assertEquals($expectedResult, $this->directpost->getRelayUrl($storeId));
176  }
177 
178  public function testAuthorize()
179  {
180  $paymentAction = 'some_action';
181 
182  $this->scopeConfigMock->expects($this->any())
183  ->method('getValue')
184  ->with('payment/authorizenet_directpost/payment_action', 'store', null)
185  ->willReturn($paymentAction);
186  $this->paymentMock->expects($this->once())
187  ->method('setAdditionalInformation')
188  ->with('payment_type', $paymentAction);
189 
190  $this->directpost->authorize($this->paymentMock, 10);
191  }
192 
193  public function testGetCgiUrl()
194  {
195  $url = 'cgi/url';
196 
197  $this->scopeConfigMock->expects($this->any())
198  ->method('getValue')
199  ->with('payment/authorizenet_directpost/cgi_url', 'store', null)
200  ->willReturn($url);
201 
202  $this->assertEquals($url, $this->directpost->getCgiUrl());
203  }
204 
206  {
207  $this->scopeConfigMock->expects($this->any())
208  ->method('getValue')
209  ->with('payment/authorizenet_directpost/cgi_url', 'store', null)
210  ->willReturn(null);
211 
212  $this->assertEquals(Directpost::CGI_URL, $this->directpost->getCgiUrl());
213  }
214 
215  public function testGetRelayUrl()
216  {
217  $storeId = 100;
218  $url = 'relay/url';
219  $this->directpost->setData('store', $storeId);
220 
221  $this->dataHelperMock->expects($this->any())
222  ->method('getRelayUrl')
223  ->with($storeId)
224  ->willReturn($url);
225 
226  $this->assertEquals($url, $this->directpost->getRelayUrl());
227  $this->assertEquals($url, $this->directpost->getRelayUrl($storeId));
228  }
229 
230  public function testGetResponse()
231  {
232  $this->assertSame($this->responseMock, $this->directpost->getResponse());
233  }
234 
235  public function testSetResponseData()
236  {
237  $data = [
238  'key' => 'value'
239  ];
240 
241  $this->responseMock->expects($this->once())
242  ->method('setData')
243  ->with($data)
244  ->willReturnSelf();
245 
246  $this->assertSame($this->directpost, $this->directpost->setResponseData($data));
247  }
248 
249  public function testValidateResponseSuccess()
250  {
251  $this->prepareTestValidateResponse('some_md5', 'login', true);
252  $this->assertEquals(true, $this->directpost->validateResponse());
253  }
254 
258  public function testValidateResponseFailure()
259  {
260  $this->prepareTestValidateResponse('some_md5', 'login', false);
261  $this->directpost->validateResponse();
262  }
263 
269  protected function prepareTestValidateResponse($transMd5, $login, $isValidHash)
270  {
271  $this->scopeConfigMock->expects($this->any())
272  ->method('getValue')
273  ->willReturnMap(
274  [
275  ['payment/authorizenet_directpost/trans_md5', 'store', null, $transMd5],
276  ['payment/authorizenet_directpost/login', 'store', null, $login]
277  ]
278  );
279  $this->responseMock->expects($this->any())
280  ->method('isValidHash')
281  ->with($transMd5, $login)
282  ->willReturn($isValidHash);
283  }
284 
285  public function testCheckTransIdSuccess()
286  {
287  $this->responseMock->expects($this->once())
288  ->method('getXTransId')
289  ->willReturn('111');
290 
291  $this->assertEquals(true, $this->directpost->checkTransId());
292  }
293 
297  public function testCheckTransIdFailure()
298  {
299  $this->responseMock->expects($this->once())
300  ->method('getXTransId')
301  ->willReturn(null);
302 
303  $this->directpost->checkTransId();
304  }
305 
311  public function testCheckResponseCodeSuccess($responseCode)
312  {
313  $this->responseMock->expects($this->once())
314  ->method('getXResponseCode')
315  ->willReturn($responseCode);
316 
317  $this->assertEquals(true, $this->directpost->checkResponseCode());
318  }
319 
324  {
325  return [
326  ['responseCode' => Directpost::RESPONSE_CODE_APPROVED],
327  ['responseCode' => Directpost::RESPONSE_CODE_HELD]
328  ];
329  }
330 
341  public function testCheckResponseCodeFailure(int $responseCode, int $failuresHandlerCalls): void
342  {
343  $reasonText = 'reason text';
344 
345  $this->responseMock->expects($this->once())
346  ->method('getXResponseCode')
347  ->willReturn($responseCode);
348  $this->responseMock->expects($this->any())
349  ->method('getXResponseReasonText')
350  ->willReturn($reasonText);
351  $this->dataHelperMock->expects($this->any())
352  ->method('wrapGatewayError')
353  ->with($reasonText)
354  ->willReturn(__('Gateway error: %1', $reasonText));
355 
356  $orderMock = $this->getMockBuilder(Order::class)
357  ->disableOriginalConstructor()
358  ->getMock();
359 
360  $orderMock->expects($this->exactly($failuresHandlerCalls))
361  ->method('getQuoteId')
362  ->willReturn(1);
363 
364  $this->paymentFailures->expects($this->exactly($failuresHandlerCalls))
365  ->method('handle')
366  ->with(1);
367 
368  $reflection = new \ReflectionClass($this->directpost);
369  $order = $reflection->getProperty('order');
370  $order->setAccessible(true);
371  $order->setValue($this->directpost, $orderMock);
372 
373  $this->directpost->checkResponseCode();
374  }
375 
379  public function checkResponseCodeFailureDataProvider(): array
380  {
381  return [
382  ['responseCode' => Directpost::RESPONSE_CODE_DECLINED, 1],
383  ['responseCode' => Directpost::RESPONSE_CODE_ERROR, 1],
384  ['responseCode' => 999999, 0],
385  ];
386  }
387 
393  public function testSetIsInitializeNeeded($isInitializeNeeded)
394  {
395  $this->directpost->setIsInitializeNeeded($isInitializeNeeded);
396  $this->assertEquals($isInitializeNeeded, $this->directpost->isInitializeNeeded());
397  }
398 
403  {
404  return [
405  ['isInitializationNeeded' => true],
406  ['isInitializationNeeded' => false]
407  ];
408  }
409 
416  public function testCanCapture($isGatewayActionsLocked, $canCapture)
417  {
418  $this->directpost->setData('info_instance', $this->paymentMock);
419 
420  $this->paymentMock->expects($this->any())
421  ->method('getAdditionalInformation')
423  ->willReturn($isGatewayActionsLocked);
424 
425  $this->assertEquals($canCapture, $this->directpost->canCapture());
426  }
427 
431  public function canCaptureDataProvider()
432  {
433  return [
434  ['isGatewayActionsLocked' => false, 'canCapture' => true],
435  ['isGatewayActionsLocked' => true, 'canCapture' => false]
436  ];
437  }
438 
450  public function testFetchVoidedTransactionInfo($transactionId, $resultStatus, $responseStatus, $responseCode)
451  {
452  $paymentId = 36;
453  $orderId = 36;
454 
455  $this->paymentMock->expects(static::once())
456  ->method('getId')
457  ->willReturn($paymentId);
458 
459  $orderMock = $this->getMockBuilder(\Magento\Sales\Model\Order::class)
460  ->disableOriginalConstructor()
461  ->setMethods(['getId', '__wakeup'])
462  ->getMock();
463  $orderMock->expects(static::once())
464  ->method('getId')
465  ->willReturn($orderId);
466 
467  $this->paymentMock->expects(static::once())
468  ->method('getOrder')
469  ->willReturn($orderMock);
470 
471  $transactionMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Payment\Transaction::class)
472  ->disableOriginalConstructor()
473  ->getMock();
474  $this->transactionRepositoryMock->expects(static::once())
475  ->method('getByTransactionId')
476  ->with($transactionId, $paymentId, $orderId)
477  ->willReturn($transactionMock);
478 
479  $document = $this->getTransactionXmlDocument(
480  $transactionId,
482  $resultStatus,
483  $responseStatus,
484  $responseCode
485  );
486  $this->transactionServiceMock->expects(static::once())
487  ->method('getTransactionDetails')
488  ->with($this->directpost, $transactionId)
489  ->willReturn($document);
490 
491  // transaction should be closed
492  $this->paymentMock->expects(static::once())
493  ->method('setIsTransactionDenied')
494  ->with(true);
495  $this->paymentMock->expects(static::once())
496  ->method('setIsTransactionClosed')
497  ->with(true);
498  $transactionMock->expects(static::once())
499  ->method('close');
500 
501  $this->directpost->fetchTransactionInfo($this->paymentMock, $transactionId);
502  }
503 
508  public function testSuccessRefund()
509  {
510  $card = 1111;
511 
512  $this->paymentMock->expects(static::exactly(2))
513  ->method('getCcLast4')
514  ->willReturn($card);
515  $this->paymentMock->expects(static::once())
516  ->method('decrypt')
517  ->willReturn($card);
518  $this->paymentMock->expects(static::exactly(3))
519  ->method('getParentTransactionId')
520  ->willReturn(self::TRANSACTION_ID . '-capture');
521  $this->paymentMock->expects(static::once())
522  ->method('getPoNumber')
523  ->willReturn(self::INVOICE_NUM);
524  $this->paymentMock->expects(static::once())
525  ->method('setIsTransactionClosed')
526  ->with(true)
527  ->willReturnSelf();
528 
529  $orderMock = $this->getOrderMock();
530 
531  $this->paymentMock->expects(static::exactly(2))
532  ->method('getOrder')
533  ->willReturn($orderMock);
534 
535  $transactionMock = $this->getMockBuilder(Order\Payment\Transaction::class)
536  ->disableOriginalConstructor()
537  ->setMethods(['getAdditionalInformation'])
538  ->getMock();
539  $transactionMock->expects(static::once())
540  ->method('getAdditionalInformation')
542  ->willReturn(self::TRANSACTION_ID);
543 
544  $this->transactionRepositoryMock->expects(static::once())
545  ->method('getByTransactionId')
546  ->willReturn($transactionMock);
547 
548  $response = $this->getRefundResponseBody(
551  'Successful'
552  );
553  $this->httpClientMock->expects(static::once())
554  ->method('getBody')
555  ->willReturn($response);
556 
557  $this->responseMock->expects(static::once())
558  ->method('getXResponseCode')
560  $this->responseMock->expects(static::once())
561  ->method('getXResponseReasonCode')
563 
564  $this->dataHelperMock->expects(static::never())
565  ->method('wrapGatewayError');
566 
567  $this->directpost->refund($this->paymentMock, self::TOTAL_AMOUNT);
568  }
569 
574  public function dataProviderTransaction()
575  {
576  return [
577  [
578  'transactionId' => '9941997799',
579  'resultStatus' => 'Successful.',
580  'responseStatus' => 'voided',
581  'responseCode' => 1
582  ]
583  ];
584  }
585 
590  private function initResponseFactoryMock()
591  {
592  $this->responseFactoryMock = $this->getMockBuilder(
593  \Magento\Authorizenet\Model\Directpost\Response\Factory::class
594  )->disableOriginalConstructor()->getMock();
595  $this->responseMock = $this->getMockBuilder(\Magento\Authorizenet\Model\Directpost\Response::class)
596  ->setMethods(
597  [
598  'isValidHash',
599  'getXTransId', 'getXResponseCode', 'getXResponseReasonCode', 'getXResponseReasonText', 'getXAmount',
600  'setXResponseCode', 'setXResponseReasonCode', 'setXAvsCode', 'setXResponseReasonText',
601  'setXTransId', 'setXInvoiceNum', 'setXAmount', 'setXMethod', 'setXType', 'setData',
602  'setXAccountNumber',
603  '__wakeup'
604  ]
605  )
606  ->disableOriginalConstructor()
607  ->getMock();
608 
609  $this->responseMock->expects(static::any())
610  ->method('setXResponseCode')
611  ->willReturnSelf();
612  $this->responseMock->expects(static::any())
613  ->method('setXResponseReasonCode')
614  ->willReturnSelf();
615  $this->responseMock->expects(static::any())
616  ->method('setXResponseReasonText')
617  ->willReturnSelf();
618  $this->responseMock->expects(static::any())
619  ->method('setXAvsCode')
620  ->willReturnSelf();
621  $this->responseMock->expects(static::any())
622  ->method('setXTransId')
623  ->willReturnSelf();
624  $this->responseMock->expects(static::any())
625  ->method('setXInvoiceNum')
626  ->willReturnSelf();
627  $this->responseMock->expects(static::any())
628  ->method('setXAmount')
629  ->willReturnSelf();
630  $this->responseMock->expects(static::any())
631  ->method('setXMethod')
632  ->willReturnSelf();
633  $this->responseMock->expects(static::any())
634  ->method('setXType')
635  ->willReturnSelf();
636  $this->responseMock->expects(static::any())
637  ->method('setData')
638  ->willReturnSelf();
639 
640  $this->responseFactoryMock->expects($this->any())
641  ->method('create')
642  ->willReturn($this->responseMock);
643  }
644 
654  private function getTransactionXmlDocument(
655  $transactionId,
656  $resultCode,
657  $resultStatus,
658  $responseStatus,
659  $responseCode
660  ) {
661  $body = sprintf(
662  '<?xml version="1.0" encoding="utf-8"?>
663  <getTransactionDetailsResponse
664  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
665  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
666  xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
667  <messages>
668  <resultCode>%s</resultCode>
669  <message>
670  <code>I00001</code>
671  <text>%s</text>
672  </message>
673  </messages>
674  <transaction>
675  <transId>%s</transId>
676  <transactionType>authOnlyTransaction</transactionType>
677  <transactionStatus>%s</transactionStatus>
678  <responseCode>%s</responseCode>
679  <responseReasonCode>%s</responseReasonCode>
680  </transaction>
681  </getTransactionDetailsResponse>',
682  $resultCode,
683  $resultStatus,
684  $transactionId,
685  $responseStatus,
686  $responseCode,
687  $responseCode
688  );
689  libxml_use_internal_errors(true);
690  $document = new Element($body);
691  libxml_use_internal_errors(false);
692  return $document;
693  }
694 
699  private function getRequestFactoryMock()
700  {
701  $requestFactory = $this->getMockBuilder(Factory::class)
702  ->disableOriginalConstructor()
703  ->setMethods(['create'])
704  ->getMock();
705  $request = $this->getMockBuilder(Request::class)
706  ->disableOriginalConstructor()
707  ->setMethods(['__wakeup'])
708  ->getMock();
709  $requestFactory->expects(static::any())
710  ->method('create')
711  ->willReturn($request);
712  return $requestFactory;
713  }
714 
719  private function getOrderMock()
720  {
721  $orderMock = $this->getMockBuilder(Order::class)
722  ->disableOriginalConstructor()
723  ->setMethods([
724  'getId', 'getIncrementId', 'getStoreId', 'getBillingAddress', 'getShippingAddress',
725  'getBaseCurrencyCode', 'getBaseTaxAmount', '__wakeup'
726  ])
727  ->getMock();
728 
729  $orderMock->expects(static::once())
730  ->method('getId')
731  ->willReturn(1);
732 
733  $orderMock->expects(static::exactly(2))
734  ->method('getIncrementId')
735  ->willReturn(self::INVOICE_NUM);
736 
737  $orderMock->expects(static::once())
738  ->method('getStoreId')
739  ->willReturn(1);
740 
741  $orderMock->expects(static::once())
742  ->method('getBaseCurrencyCode')
743  ->willReturn('USD');
744  return $orderMock;
745  }
746 
751  private function getHttpClientFactoryMock()
752  {
753  $this->httpClientMock = $this->getMockBuilder(\Magento\Framework\HTTP\ZendClient::class)
754  ->disableOriginalConstructor()
755  ->setMethods(['request', 'getBody', '__wakeup'])
756  ->getMock();
757 
758  $this->httpClientMock->expects(static::any())
759  ->method('request')
760  ->willReturnSelf();
761 
762  $httpClientFactoryMock = $this->getMockBuilder(\Magento\Framework\HTTP\ZendClientFactory::class)
763  ->disableOriginalConstructor()
764  ->setMethods(['create'])
765  ->getMock();
766 
767  $httpClientFactoryMock->expects(static::any())
768  ->method('create')
769  ->willReturn($this->httpClientMock);
770  return $httpClientFactoryMock;
771  }
772 
780  private function getRefundResponseBody($code, $reasonCode, $reasonText)
781  {
782  $result = array_fill(0, 50, '');
783  $result[0] = $code; // XResponseCode
784  $result[2] = $reasonCode; // XResponseReasonCode
785  $result[3] = $reasonText; // XResponseReasonText
786  $result[6] = self::TRANSACTION_ID; // XTransId
787  $result[7] = self::INVOICE_NUM; // XInvoiceNum
788  $result[9] = self::TOTAL_AMOUNT; // XAmount
789  $result[10] = Directpost::REQUEST_METHOD_CC; // XMethod
791  $result[37] = md5(self::TRANSACTION_ID); // x_MD5_Hash
792  $result[50] = '48329483921'; // setXAccountNumber
793  return implode(Directpost::RESPONSE_DELIM_CHAR, $result);
794  }
795 }
testCanCapture($isGatewayActionsLocked, $canCapture)
$response
Definition: 404.php:11
$helper
Definition: iframe.phtml:13
testCheckResponseCodeFailure(int $responseCode, int $failuresHandlerCalls)
$order
Definition: order.php:55
__()
Definition: __.php:13
prepareTestValidateResponse($transMd5, $login, $isValidHash)
testFetchVoidedTransactionInfo($transactionId, $resultStatus, $responseStatus, $responseCode)
$code
Definition: info.phtml:12