IndexV2   F
last analyzed

Complexity

Total Complexity 91

Size/Duplication

Total Lines 791
Duplicated Lines 0 %

Importance

Changes 26
Bugs 0 Features 0
Metric Value
eloc 362
c 26
b 0
f 0
dl 0
loc 791
rs 2
wmc 91

31 Methods

Rating   Name   Duplication   Size   Complexity  
C execute() 0 78 9
A getMerchantOrder() 0 7 2
B blockConcurrency() 0 39 6
A confirmpagantisOrder() 0 14 2
A checkConcurrency() 0 6 1
A rollbackMerchantOrder() 0 8 2
A processMerchantOrder() 0 7 2
A saveOrder() 0 38 5
A getPagantisOrder() 0 17 3
A setOrigin() 0 3 1
A checkDbTable() 0 11 2
A unblockConcurrency() 0 13 4
A getQuoteId() 0 5 2
A updateBdInfo() 0 14 2
A setProduct() 0 3 1
A insertLog() 0 21 5
A isRedirect() 0 3 1
A createCsrfValidationException() 0 3 1
A getPagantisOrderId() 0 14 3
A getOrigin() 0 3 1
A validateForCsrf() 0 3 1
A checkOrderStatus() 0 10 3
A getProduct() 0 3 1
A checkDbLogTable() 0 28 3
B getRedirectUrl() 0 53 10
A getMagentoOrderId() 0 23 3
A checkMerchantOrderStatus() 0 5 2
A checkPagantisStatus() 0 10 3
A validateAmount() 0 6 2
A isNotification() 0 3 1
B __construct() 0 37 7

How to fix   Complexity   

Complex Class

Complex classes like IndexV2 often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use IndexV2, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Pagantis\Pagantis\Controller\Notify;
4
5
use Magento\Quote\Model\QuoteManagement;
6
use Magento\Quote\Api\Data\PaymentInterface;
7
use Magento\Sales\Api\Data\OrderInterface;
8
use Magento\Sales\Api\OrderRepositoryInterface;
9
use Magento\Quote\Model\Quote;
10
use Magento\Quote\Model\QuoteRepository;
11
use Magento\Framework\App\Action\Context;
12
use Magento\Framework\App\Action\Action;
13
use Pagantis\ModuleUtils\Exception\MerchantOrderNotFoundException;
14
use Pagantis\OrdersApiClient\Client;
15
use Pagantis\Pagantis\Helper\Config;
16
use Pagantis\Pagantis\Helper\ExtraConfig;
17
use Magento\Framework\App\ResourceConnection;
18
use Magento\Checkout\Model\Session;
19
use Magento\Framework\DB\Ddl\Table;
20
use Pagantis\ModuleUtils\Exception\AmountMismatchException;
21
use Pagantis\ModuleUtils\Exception\ConcurrencyException;
22
use Pagantis\ModuleUtils\Exception\NoIdentificationException;
23
use Pagantis\ModuleUtils\Exception\OrderNotFoundException;
24
use Pagantis\ModuleUtils\Exception\QuoteNotFoundException;
25
use Pagantis\ModuleUtils\Exception\UnknownException;
26
use Pagantis\ModuleUtils\Exception\WrongStatusException;
27
use Pagantis\ModuleUtils\Model\Response\JsonSuccessResponse;
28
use Pagantis\ModuleUtils\Model\Response\JsonExceptionResponse;
29
use Pagantis\ModuleUtils\Exception\AlreadyProcessedException;
30
use Pagantis\ModuleUtils\Model\Log\LogEntry;
31
use Magento\Framework\App\RequestInterface;
32
use Magento\Framework\App\Request\InvalidRequestException;
33
use Pagantis\Pagantis\Model\Ui\ConfigProvider;
34
35
/**
36
 * Class Index
37
 * @package Pagantis\Pagantis\Controller\Notify
38
 */
39
class IndexV2 extends Action
40
{
41
    /** Orders tablename */
42
    const ORDERS_TABLE = 'cart_process';
43
44
    /** Concurrency tablename */
45
    const CONCURRENCY_TABLE = 'Pagantis_orders';
46
47
    /** Concurrency tablename */
48
    const LOGS_TABLE = 'Pagantis_logs';
49
50
    /** Seconds to expire a locked request */
51
    const CONCURRENCY_TIMEOUT = 10;
52
53
    /**
54
     * EXCEPTION RESPONSES
55
     */
56
    const CPO_ERR_MSG = 'Order not confirmed';
57
    const CPO_OK_MSG = 'Order confirmed';
58
59
    /** @var QuoteManagement */
60
    protected $quoteManagement;
61
62
    /** @var PaymentInterface $paymentInterface */
63
    protected $paymentInterface;
64
65
    /** @var OrderRepositoryInterface $orderRepositoryInterface */
66
    protected $orderRepositoryInterface;
67
68
    /** @var Quote $quote */
69
    protected $quote;
70
71
    /** @var QuoteRepository $quoteRepository */
72
    protected $quoteRepository;
73
74
    /** @var mixed $config */
75
    protected $config;
76
77
    /** @var mixed $quoteId */
78
    protected $quoteId;
79
80
    /** @var array $notifyResult */
81
    protected $notifyResult;
82
83
    /** @var mixed $magentoOrderId */
84
    protected $magentoOrderId;
85
86
    /** @var mixed $pagantisOrder */
87
    protected $pagantisOrder;
88
89
    /** @var ResourceConnection $dbObject */
90
    protected $dbObject;
91
92
    /** @var Session $checkoutSession */
93
    protected $checkoutSession;
94
95
    /** @var Client $orderClient */
96
    protected $orderClient;
97
98
    /** @var mixed $pagantisOrderId */
99
    protected $pagantisOrderId;
100
101
    /** @var  OrderInterface $magentoOrder */
102
    protected $magentoOrder;
103
104
    /** @var ExtraConfig $extraConfig */
105
    protected $extraConfig;
106
107
    /** @var mixed $origin */
108
    protected $origin;
109
110
    /** @var mixed $product */
111
    protected $product;
112
113
    /** @var RequestInterface $_request*/
114
    protected $_request;
115
116
    /** @var mixed $origin */
117
    protected $token;
118
119
    /**
120
     * IndexV2 constructor.
121
     *
122
     * @param Context                  $context
123
     * @param Quote                    $quote
124
     * @param QuoteManagement          $quoteManagement
125
     * @param PaymentInterface         $paymentInterface
126
     * @param Config                   $config
127
     * @param QuoteRepository          $quoteRepository
128
     * @param OrderRepositoryInterface $orderRepositoryInterface
129
     * @param ResourceConnection       $dbObject
130
     * @param Session                  $checkoutSession
131
     * @param ExtraConfig              $extraConfig
132
     * @param RequestInterface         $request
133
     */
134
    public function __construct(
135
        Context $context,
136
        Quote $quote,
137
        QuoteManagement $quoteManagement,
138
        PaymentInterface $paymentInterface,
139
        Config $config,
140
        QuoteRepository $quoteRepository,
141
        OrderRepositoryInterface $orderRepositoryInterface,
142
        ResourceConnection $dbObject,
143
        Session $checkoutSession,
144
        ExtraConfig $extraConfig,
145
        RequestInterface $request
146
    ) {
147
        parent::__construct($context);
148
149
        $this->quote = $quote;
150
        $this->quoteManagement = $quoteManagement;
151
        $this->paymentInterface = $paymentInterface;
152
        $this->extraConfig = $extraConfig->getExtraConfig();
0 ignored issues
show
Documentation Bug introduced by pgarces
It seems like $extraConfig->getExtraConfig() of type array or array is incompatible with the declared type Pagantis\Pagantis\Helper\ExtraConfig of property $extraConfig.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
153
        $this->config = $config->getConfig();
154
        $this->quoteRepository = $quoteRepository;
155
        $this->orderRepositoryInterface = $orderRepositoryInterface;
156
        $this->dbObject = $dbObject;
157
        $this->checkoutSession = $checkoutSession;
158
        $this->_request = $request;
159
        $this->origin = (
160
            $this->_request->isPost() || $this->_request->getParam('origin')=='notification'
0 ignored issues
show
Bug introduced by pgarces
The method isPost() does not exist on Magento\Framework\App\RequestInterface. It seems like you code against a sub-type of Magento\Framework\App\RequestInterface such as Magento\Framework\Webapi\Request or Magento\Framework\App\Request\Http. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

160
            $this->_request->/** @scrutinizer ignore-call */ 
161
                             isPost() || $this->_request->getParam('origin')=='notification'
Loading history...
161
                        ) ? 'Notification' : 'Order';
162
        $this->product = $this->_request->getParam('product');
163
        $this->token = $this->_request->getParam('token');
164
165
        // CsrfAwareAction Magento2.3 compatibility
166
        if (interface_exists("\Magento\Framework\App\CsrfAwareActionInterface")) {
167
            if (isset($request) && $request->isPost() && empty($request->getParam('form_key'))) {
168
                $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
169
                $formKey = $objectManager->get(\Magento\Framework\Data\Form\FormKey::class);
170
                $request->setParam('form_key', $formKey->getFormKey());
0 ignored issues
show
Bug introduced by pgarces
The method setParam() does not exist on Magento\Framework\App\RequestInterface. Did you maybe mean setParams()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

170
                $request->/** @scrutinizer ignore-call */ 
171
                          setParam('form_key', $formKey->getFormKey());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
171
            }
172
        }
173
    }
174
175
    /**
176
     * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface|void
177
     * @throws UnknownException
178
     */
179
    public function execute()
180
    {
181
182
        $thrownException = false;
183
        try {
184
            if ($this->_request->isGet() && $this->isNotification()) {
0 ignored issues
show
Bug introduced by pgarces
The method isGet() does not exist on Magento\Framework\App\RequestInterface. It seems like you code against a sub-type of Magento\Framework\App\RequestInterface such as Magento\Framework\Webapi\Request or Magento\Framework\App\Request\Http. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

184
            if ($this->_request->/** @scrutinizer ignore-call */ isGet() && $this->isNotification()) {
Loading history...
185
                echo 'OK';
186
                die;
0 ignored issues
show
Best Practice introduced by pgarces
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
187
            }
188
189
            if ($this->_request->isGet() && $this->isRedirect()) {
190
                $redirectMessage = sprintf(
191
                    "[origin=%s][quoteId=%s]",
192
                    $this->getOrigin(),
193
                    $this->getRequest()->getParam('quoteId')
194
                );
195
                $this->insertLog(null, $redirectMessage);
196
            }
197
198
            $this->checkConcurrency();
199
            $this->getMerchantOrder();
200
            $this->getPagantisOrderId();
201
            $this->getPagantisOrder();
202
            $this->checkOrderStatus();
203
            $this->checkMerchantOrderStatus();
204
            $this->validateAmount();
205
            $this->processMerchantOrder();
206
        } catch (\Exception $exception) {
207
            $thrownException = true;
208
            $jsonResponse = new JsonExceptionResponse();
209
            $jsonResponse->setMerchantOrderId($this->magentoOrderId);
210
            $jsonResponse->setpagantisOrderId($this->pagantisOrderId);
211
            $jsonResponse->setException($exception);
212
            $this->insertLog($exception);
213
        }
214
215
        try {
216
            if (!$thrownException) {
217
                $this->confirmpagantisOrder();
218
                $jsonResponse = new JsonSuccessResponse();
219
                $jsonResponse->setMerchantOrderId($this->magentoOrderId);
220
                $jsonResponse->setpagantisOrderId($this->pagantisOrderId);
221
            }
222
        } catch (\Exception $exception) {
223
            $this->rollbackMerchantOrder();
224
            $jsonResponse = new JsonExceptionResponse();
225
            $jsonResponse->setMerchantOrderId($this->magentoOrderId);
226
            $jsonResponse->setpagantisOrderId($this->pagantisOrderId);
227
            $jsonResponse->setException($exception);
228
            $jsonResponse->toJson();
229
            $this->insertLog($exception);
230
        }
231
232
        $this->unblockConcurrency(true);
233
234
        if ($this->isNotification()) {
235
            $returnMessage = sprintf(
236
                "[origin=%s][quoteId=%s][magentoOrderId=%s][pagantisOrderId=%s][message=%s]",
237
                $this->getOrigin(),
238
                $this->quoteId,
239
                $this->magentoOrderId,
240
                $this->pagantisOrderId,
241
                $jsonResponse->getResult()
0 ignored issues
show
Comprehensibility Best Practice introduced by pgarces
The variable $jsonResponse does not seem to be defined for all execution paths leading up to this point.
Loading history...
242
            );
243
            $this->insertLog(null, $returnMessage);
244
            $jsonResponse->printResponse();
245
        } else {
246
            $returnUrl = $this->getRedirectUrl();
247
            $returnMessage = sprintf(
248
                "[origin=%s][quoteId=%s][magentoOrderId=%s][pagantisOrderId=%s][returnUrl=%s]",
249
                $this->getOrigin(),
250
                $this->quoteId,
251
                $this->magentoOrderId,
252
                $this->pagantisOrderId,
253
                $returnUrl
254
            );
255
            $this->insertLog(null, $returnMessage);
256
            $this->_redirect($returnUrl);
257
        }
258
    }
259
260
    /**
261
     * COMMON FUNCTIONS
262
     */
263
264
    /**
265
     * @throws ConcurrencyException
266
     * @throws QuoteNotFoundException
267
     * @throws UnknownException
268
     */
269
    private function checkConcurrency()
270
    {
271
        $this->getQuoteId();
272
        $this->checkDbTable();
273
        $this->unblockConcurrency();
274
        $this->blockConcurrency();
275
    }
276
277
    /**
278
     * @throws MerchantOrderNotFoundException
279
     */
280
    private function getMerchantOrder()
281
    {
282
        try {
283
            /** @var Quote quote */
284
            $this->quote = $this->quoteRepository->get($this->quoteId);
285
        } catch (\Exception $e) {
286
            throw new MerchantOrderNotFoundException();
287
        }
288
    }
289
290
    /**
291
     * @throws UnknownException
292
     */
293
    private function getPagantisOrderId()
294
    {
295
        try {
296
            /** @var \Magento\Framework\DB\Adapter\AdapterInterface $dbConnection */
297
            $dbConnection     = $this->dbObject->getConnection();
298
            $tableName        = $this->dbObject->getTableName(self::ORDERS_TABLE);
299
            $query            = "select order_id from $tableName where id='".$this->quoteId."' and token='".$this->token."'";
300
            $queryResult      = $dbConnection->fetchRow($query);
301
            $this->pagantisOrderId = $queryResult['order_id'];
302
            if ($this->pagantisOrderId == '') {
303
                throw new NoIdentificationException();
304
            }
305
        } catch (\Exception $e) {
306
            throw new UnknownException($e->getMessage());
307
        }
308
    }
309
310
    /**
311
     * @throws OrderNotFoundException
312
     */
313
    private function getPagantisOrder()
314
    {
315
        try {
316
            if ($this->getProduct()===ConfigProvider::CODE4X) {
317
                $this->orderClient = new Client(
318
                    $this->config['pagantis_public_key_4x'],
319
                    $this->config['pagantis_private_key_4x']
320
                );
321
            } else {
322
                $this->orderClient = new Client(
323
                    $this->config['pagantis_public_key'],
324
                    $this->config['pagantis_private_key']
325
                );
326
            }
327
            $this->pagantisOrder = $this->orderClient->getOrder($this->pagantisOrderId);
328
        } catch (\Exception $e) {
329
            throw new OrderNotFoundException();
330
        }
331
    }
332
333
    /**
334
     * @throws AlreadyProcessedException
335
     * @throws WrongStatusException
336
     */
337
    private function checkOrderStatus()
338
    {
339
        try {
340
            $this->checkPagantisStatus(array('AUTHORIZED'));
341
        } catch (\Exception $e) {
342
            $this->getMagentoOrderId();
343
            if ($this->magentoOrderId!='') {
344
                throw new AlreadyProcessedException();
345
            } else {
346
                throw new WrongStatusException($this->pagantisOrder->getStatus());
347
            }
348
        }
349
    }
350
351
    /**
352
     * @throws AlreadyProcessedException
353
     */
354
    private function checkMerchantOrderStatus()
355
    {
356
        if ($this->quote->getIsActive()=='0') {
357
            $this->getMagentoOrderId();
358
            throw new AlreadyProcessedException();
359
        }
360
    }
361
362
    /**
363
     * @throws AmountMismatchException
364
     */
365
    private function validateAmount()
366
    {
367
        $pagantisAmount = $this->pagantisOrder->getShoppingCart()->getTotalAmount();
368
        $merchantAmount = intval(100 * $this->quote->getGrandTotal());
369
        if ($pagantisAmount != $merchantAmount) {
370
            throw new AmountMismatchException($pagantisAmount, $merchantAmount);
371
        }
372
    }
373
374
    /**
375
     * @throws UnknownException
376
     */
377
    private function processMerchantOrder()
378
    {
379
        try {
380
            $this->saveOrder();
381
            $this->updateBdInfo();
382
        } catch (\Exception $e) {
383
            throw new UnknownException($e->getMessage());
384
        }
385
    }
386
387
    /**
388
     * @return false|string
389
     * @throws UnknownException
390
     */
391
    private function confirmpagantisOrder()
392
    {
393
        try {
394
            $this->pagantisOrder = $this->orderClient->confirmOrder($this->pagantisOrderId);
395
        } catch (\Exception $e) {
396
            throw new UnknownException(sprintf("[%s]%s", $this->getOrigin(), $e->getMessage()));
397
        }
398
399
        $jsonResponse = new JsonSuccessResponse();
400
        $jsonResponse->setStatusCode(200);
401
        $jsonResponse->setMerchantOrderId($this->magentoOrderId);
402
        $jsonResponse->setpagantisOrderId($this->pagantisOrderId);
403
        $jsonResponse->setResult(self::CPO_OK_MSG);
404
        return $jsonResponse->toJson();
405
    }
406
407
    /**
408
     * UTILS FUNCTIONS
409
     */
410
411
    /** STEP 1 CC - Check concurrency
412
     * @throws QuoteNotFoundException
413
     */
414
    private function getQuoteId()
415
    {
416
        $this->quoteId = $this->getRequest()->getParam('quoteId');
417
        if ($this->quoteId == '') {
418
            throw new QuoteNotFoundException();
419
        }
420
    }
421
422
    /**
423
     * @return \Zend_Db_Statement_Interface
424
     * @throws UnknownException
425
     */
426
    private function checkDbTable()
427
    {
428
        try {
429
            /** @var \Magento\Framework\DB\Adapter\AdapterInterface $dbConnection */
430
            $dbConnection = $this->dbObject->getConnection();
431
            $tableName    = $this->dbObject->getTableName(self::CONCURRENCY_TABLE);
432
            $query = "CREATE TABLE IF NOT EXISTS $tableName(`id` int not null,`timestamp` int not null,PRIMARY KEY (`id`))";
433
434
            return $dbConnection->query($query);
435
        } catch (\Exception $e) {
436
            throw new UnknownException($e->getMessage());
437
        }
438
    }
439
440
    /**
441
     * @return void|\Zend_Db_Statement_Interface
442
     * @throws UnknownException
443
     */
444
    private function checkDbLogTable()
445
    {
446
        try {
447
            /** @var \Magento\Framework\DB\Adapter\AdapterInterface $dbConnection */
448
            $dbConnection = $this->dbObject->getConnection();
449
            $tableName = $this->dbObject->getTableName(self::LOGS_TABLE);
450
            if (!$dbConnection->isTableExists($tableName)) {
451
                $table = $dbConnection
452
                    ->newTable($tableName)
453
                    ->addColumn(
454
                        'id',
455
                        Table::TYPE_SMALLINT,
456
                        null,
457
                        array('nullable'=>false, 'auto_increment'=>true, 'primary'=>true)
458
                    )
459
                    ->addColumn('log', Table::TYPE_TEXT, null, array('nullable'=>false))
460
                    ->addColumn(
461
                        'createdAt',
462
                        Table::TYPE_TIMESTAMP,
463
                        null,
464
                        array('nullable'=>false, 'default'=>Table::TIMESTAMP_INIT)
465
                    );
466
                return $dbConnection->createTable($table);
467
            }
468
469
            return;
470
        } catch (\Exception $e) {
471
            throw new UnknownException($e->getMessage());
472
        }
473
    }
474
475
    /**
476
     * @param bool $mode
477
     *
478
     * @throws \Exception
479
     */
480
    private function unblockConcurrency($mode = false)
481
    {
482
        try {
483
            /** @var \Magento\Framework\DB\Adapter\AdapterInterface $dbConnection */
484
            $dbConnection = $this->dbObject->getConnection();
485
            $tableName    = $this->dbObject->getTableName(self::CONCURRENCY_TABLE);
486
            if ($mode == false) {
0 ignored issues
show
Coding Style Best Practice introduced by pgarces
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
487
                $dbConnection->delete($tableName, "timestamp<".(time() - 5));
488
            } elseif ($this->quoteId!='') {
489
                $dbConnection->delete($tableName, "id=".$this->quoteId);
490
            }
491
        } catch (Exception $exception) {
0 ignored issues
show
Bug introduced by pgarces
The type Pagantis\Pagantis\Controller\Notify\Exception was not found. Did you mean Exception? If so, make sure to prefix the type with \.
Loading history...
492
            throw new ConcurrencyException();
493
        }
494
    }
495
496
    /**
497
     * @throws ConcurrencyException
498
     * @throws UnknownException
499
     */
500
    private function blockConcurrency()
501
    {
502
        /** @var \Magento\Framework\DB\Adapter\AdapterInterface $dbConnection */
503
        $dbConnection = $this->dbObject->getConnection();
504
        $tableName    = $this->dbObject->getTableName(self::CONCURRENCY_TABLE);
505
        $query = "SELECT timestamp FROM $tableName where id='$this->quoteId'";
506
        $resultsSelect = $dbConnection->fetchRow($query);
507
        if (isset($resultsSelect['timestamp'])) {
508
            if ($this->isNotification()) {
509
                throw new ConcurrencyException();
510
            } else {
511
                $query = sprintf(
512
                    "SELECT timestamp - %s as rest FROM %s %s",
513
                    (time() - self::CONCURRENCY_TIMEOUT),
514
                    $tableName,
515
                    "WHERE id='".$this->quoteId."'"
516
                );
517
                $resultsSelect = $dbConnection->fetchRow($query);
518
                $restSeconds   = isset($resultsSelect['rest']) ? ($resultsSelect['rest']) : 0;
519
                $expirationSec = ($restSeconds > self::CONCURRENCY_TIMEOUT) ? self::CONCURRENCY_TIMEOUT : $restSeconds;
520
                if ($expirationSec > 0) {
521
                    sleep($expirationSec + 1);
522
                }
523
524
                $this->getPagantisOrderId();
525
                $this->getMagentoOrderId();
526
527
                $logMessage  = sprintf(
528
                    "User waiting %s seconds, default seconds %s, bd time to expire %s seconds[quoteId=%s][origin=%s]",
529
                    $expirationSec,
530
                    self::CONCURRENCY_TIMEOUT,
531
                    $restSeconds,
532
                    $this->quoteId,
533
                    $this->getOrigin()
534
                );
535
                throw new UnknownException($logMessage);
536
            }
537
        } else {
538
            $dbConnection->insert($tableName, array('id'=>$this->quoteId, 'timestamp'=>time()));
539
        }
540
    }
541
542
    /** STEP 2 GMO - Get Merchant Order */
543
    /** STEP 3 GPOI - Get Pagantis OrderId */
544
    /** STEP 4 GPO - Get Pagantis Order */
545
    /** STEP 5 COS - Check Order Status */
546
    /**
547
     * @param $statusArray
548
     *
549
     * @throws \Exception
550
     */
551
    private function checkPagantisStatus($statusArray)
552
    {
553
        $pagantisStatus = array();
554
        foreach ($statusArray as $status) {
555
            $pagantisStatus[] = constant("\Pagantis\OrdersApiClient\Model\Order::STATUS_$status");
556
        }
557
558
        $payed = in_array($this->pagantisOrder->getStatus(), $pagantisStatus);
559
        if (!$payed) {
560
            throw new WrongStatusException($this->pagantisOrder->getStatus());
561
        }
562
    }
563
564
    /** STEP 6 CMOS - Check Merchant Order Status */
565
    /**
566
     * @throws \Exception
567
     */
568
    private function getMagentoOrderId()
569
    {
570
        try {
571
            /** @var \Magento\Framework\DB\Adapter\AdapterInterface $dbConnection */
572
            $dbConnection = $this->dbObject->getConnection();
573
            $tableName    = $this->dbObject->getTableName(self::ORDERS_TABLE);
574
575
            if ($this->pagantisOrderId == '') {
576
                $this->getPagantisOrderId();
577
            }
578
579
            $pagantisOrderId   = $this->pagantisOrderId;
580
            $query = sprintf(
581
                "select mg_order_id from %s where id='%s' and order_id='%s' and token='%s'",
582
                $tableName,
583
                $this->quoteId,
584
                $pagantisOrderId,
585
                $this->token
586
            );
587
            $queryResult  = $dbConnection->fetchRow($query);
588
            $this->magentoOrderId = $queryResult['mg_order_id'];
589
        } catch (\Exception $e) {
590
            throw new UnknownException($e->getMessage());
591
        }
592
    }
593
594
    /** STEP 7 VA - Validate Amount */
595
    /** STEP 8 PMO - Process Merchant Order */
596
    /**
597
     * @throws UnknownException
598
     */
599
    private function saveOrder()
600
    {
601
        try {
602
            $this->paymentInterface->setMethod($this->getProduct());
603
            $this->magentoOrderId = $this->quoteManagement->placeOrder($this->quoteId, $this->paymentInterface);
604
            /** @var OrderRepositoryInterface magentoOrder */
605
            $this->magentoOrder = $this->orderRepositoryInterface->get($this->magentoOrderId);
606
            $metadataOrder = $this->pagantisOrder->getMetadata();
607
            $metadataInfo = null;
608
            foreach ($metadataOrder as $metadataKey => $metadataValue) {
609
                if ($metadataKey == 'promotedProduct') {
610
                    $metadataInfo.= "/Producto promocionado = $metadataValue";
611
                }
612
            }
613
614
            $this->magentoOrder->addStatusHistoryComment($metadataInfo)
615
                               ->setIsCustomerNotified(false)
616
                               ->setEntityName('order')
617
                               ->save();
618
619
            $comment = sprintf(
620
                'pagantisOrderId: %s || pagantisOrderStatus: %s  || via: %s  || product: %s',
621
                $this->pagantisOrder->getId(),
622
                $this->pagantisOrder->getStatus(),
623
                $this->getOrigin(),
624
                $this->getProduct()
625
            );
626
627
            $this->magentoOrder->addStatusHistoryComment($comment)
628
                               ->setIsCustomerNotified(false)
629
                               ->setEntityName('order')
630
                               ->save();
631
632
            if ($this->magentoOrderId == '') {
633
                throw new UnknownException('Order can not be saved');
634
            }
635
        } catch (\Exception $e) {
636
            throw new UnknownException($e->getMessage());
637
        }
638
    }
639
640
    /**
641
     * @throws UnknownException
642
     */
643
    private function updateBdInfo()
644
    {
645
        try {
646
            /** @var \Magento\Framework\DB\Adapter\AdapterInterface $dbConnection */
647
            $dbConnection = $this->dbObject->getConnection();
648
            $tableName    = $this->dbObject->getTableName(self::ORDERS_TABLE);
649
            $pagantisOrderId   = $this->pagantisOrder->getId();
650
            $dbConnection->update(
651
                $tableName,
652
                array('mg_order_id' => $this->magentoOrderId),
653
                "order_id='$pagantisOrderId' and id='$this->quoteId'"
654
            );
655
        } catch (\Exception $e) {
656
            throw new UnknownException($e->getMessage());
657
        }
658
    }
659
660
    /** STEP 9 CPO - Confirmation Pagantis Order */
661
    /**
662
     * @throws UnknownException
663
     */
664
    private function rollbackMerchantOrder()
665
    {
666
        try {
667
            $this->magentoOrder->setState(\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT, true);
0 ignored issues
show
Unused Code introduced by pgarces
The call to Magento\Sales\Api\Data\OrderInterface::setState() has too many arguments starting with true. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

667
            $this->magentoOrder->/** @scrutinizer ignore-call */ 
668
                                 setState(\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT, true);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
668
            $this->magentoOrder->setStatus(\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT);
669
            $this->magentoOrder->save();
670
        } catch (\Exception $e) {
671
            throw new UnknownException($e->getMessage());
672
        }
673
    }
674
675
    /**
676
     * @return mixed
677
     */
678
    public function getOrigin()
679
    {
680
        return $this->origin;
681
    }
682
683
    /**
684
     * @param mixed $origin
685
     */
686
    public function setOrigin($origin)
687
    {
688
        $this->origin = $origin;
689
    }
690
691
    /**
692
     * @return mixed
693
     */
694
    public function getProduct()
695
    {
696
        return $this->product;
697
    }
698
699
    /**
700
     * @param mixed $product
701
     */
702
    public function setProduct($product)
703
    {
704
        $this->product = $product;
705
    }
706
707
    /**
708
     * @return string
709
     * @throws UnknownException
710
     */
711
    private function getRedirectUrl()
712
    {
713
        //$returnUrl = 'checkout/#payment';
714
        $returnUrl = $this->_url->getUrl('checkout', ['_fragment' => 'payment']);
715
716
        if ($this->pagantisOrderId == '') {
717
            $this->getPagantisOrderId();
718
        }
719
720
        if ($this->magentoOrderId == '') {
721
            $this->getMagentoOrderId();
722
        }
723
724
        if ($this->magentoOrderId!='') {
725
            /** @var Order $this->magentoOrder */
726
            $this->magentoOrder = $this->orderRepositoryInterface->get($this->magentoOrderId);
727
            if (!$this->_objectManager->get(\Magento\Checkout\Model\Session\SuccessValidator::class)->isValid()) {
728
                $checkoutMessage = sprintf(
729
                    "[origin=%s][quoteId=%s][magentoOrderId=%s][pagantisOrderId=%s]Setting checkout session",
730
                    $this->getOrigin(),
731
                    $this->quoteId,
732
                    $this->magentoOrderId,
733
                    $this->pagantisOrderId
734
                );
735
                $this->insertLog(null, $checkoutMessage);
736
                $this->checkoutSession
737
                    ->setLastOrderId($this->magentoOrderId)
738
                    ->setLastRealOrderId($this->magentoOrder->getIncrementId())
739
                    ->setLastQuoteId($this->quoteId)
740
                    ->setLastSuccessQuoteId($this->quoteId)
741
                    ->setLastOrderStatus($this->magentoOrder->getStatus());
742
            }
743
744
            //Magento status flow => https://docs.magento.com/m2/ce/user_guide/sales/order-status-workflow.html
745
            //Order Workflow => https://docs.magento.com/m2/ce/user_guide/sales/order-workflow.html
746
            $orderStatus    = strtolower($this->magentoOrder->getStatus());
747
            $acceptedStatus = array('processing', 'completed');
748
            if (in_array($orderStatus, $acceptedStatus)) {
749
                if (isset($this->extraConfig['PAGANTIS_OK_URL']) &&  $this->extraConfig['PAGANTIS_OK_URL']!= '') {
750
                    $returnUrl = $this->extraConfig['PAGANTIS_OK_URL'];
751
                } else {
752
                    $returnUrl = 'checkout/onepage/success';
753
                }
754
            } else {
755
                if (isset($this->extraConfig['PAGANTIS_KO_URL']) && $this->extraConfig['PAGANTIS_KO_URL'] != '') {
756
                    $returnUrl = $this->extraConfig['PAGANTIS_KO_URL'];
757
                } else {
758
                    //$returnUrl = 'checkout/#payment';
759
                    $returnUrl = $this->_url->getUrl('checkout', ['_fragment' => 'payment']);
760
                }
761
            }
762
        }
763
        return $returnUrl;
764
    }
765
766
    /**
767
     * @param null $exceptionMessage
0 ignored issues
show
Documentation Bug introduced by pgarces
Are you sure the doc-type for parameter $exceptionMessage is correct as it would always require null to be passed?
Loading history...
768
     * @param null $logMessage
0 ignored issues
show
Documentation Bug introduced by pgarces
Are you sure the doc-type for parameter $logMessage is correct as it would always require null to be passed?
Loading history...
769
     *
770
     * @throws UnknownException
771
     */
772
    private function insertLog($exceptionMessage = null, $logMessage = null)
773
    {
774
        try {
775
            $this->checkDbLogTable();
776
            $logEntryJson = '';
777
            if ($exceptionMessage instanceof \Exception) {
778
                $logEntry     = new LogEntry();
779
                $logEntryJson = $logEntry->error($exceptionMessage)->toJson();
780
            } elseif ($logMessage != null) {
0 ignored issues
show
introduced by pgarces
The condition $logMessage != null is always false.
Loading history...
781
                $logEntry     = new LogEntry();
782
                $logEntryJson = $logEntry->info($logMessage)->toJson();
783
            }
784
785
            if ($logEntryJson != '') {
786
                /** @var \Magento\Framework\DB\Adapter\AdapterInterface $dbConnection */
787
                $dbConnection = $this->dbObject->getConnection();
788
                $tableName    = $this->dbObject->getTableName(self::LOGS_TABLE);
789
                $dbConnection->insert($tableName, array('log' => $logEntryJson));
790
            }
791
        } catch (\Exception $e) {
792
            throw new UnknownException($e->getMessage());
793
        }
794
    }
795
796
    /**
797
     * @return bool
798
     */
799
    private function isNotification()
800
    {
801
        return ($this->getOrigin() == 'Notification');
802
    }
803
804
    /**
805
     * @return bool
806
     */
807
    private function isRedirect()
808
    {
809
        return ($this->getOrigin() == 'Order');
810
    }
811
812
    /**
813
     * @param RequestInterface $request
814
     *
815
     * @return InvalidRequestException|null
816
     */
817
    public function createCsrfValidationException(RequestInterface $request)
0 ignored issues
show
Unused Code introduced by pgarces
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

817
    public function createCsrfValidationException(/** @scrutinizer ignore-unused */ RequestInterface $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
818
    {
819
        return null;
820
    }
821
822
    /**
823
     * @param RequestInterface $request
824
     *
825
     * @return bool|null
826
     */
827
    public function validateForCsrf(RequestInterface $request)
0 ignored issues
show
Unused Code introduced by pgarces
The parameter $request is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

827
    public function validateForCsrf(/** @scrutinizer ignore-unused */ RequestInterface $request)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
828
    {
829
        return true;
830
    }
831
}
832