Passed
Pull Request — master (#4)
by Raúl
02:06
created

pagantisNotify::saveOrder()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 10
nc 2
nop 0
dl 0
loc 13
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
use Pagantis\OrdersApiClient\Client;
4
use Pagantis\ModuleUtils\Exception\AlreadyProcessedException;
5
use Pagantis\ModuleUtils\Exception\AmountMismatchException;
6
use Pagantis\ModuleUtils\Exception\MerchantOrderNotFoundException;
7
use Pagantis\ModuleUtils\Exception\NoIdentificationException;
8
use Pagantis\ModuleUtils\Exception\OrderNotFoundException;
9
use Pagantis\ModuleUtils\Exception\QuoteNotFoundException;
10
use Pagantis\ModuleUtils\Exception\UnknownException;
11
use Pagantis\ModuleUtils\Exception\WrongStatusException;
12
use Pagantis\ModuleUtils\Model\Response\JsonSuccessResponse;
13
use Pagantis\ModuleUtils\Model\Response\JsonExceptionResponse;
14
use Pagantis\ModuleUtils\Model\Log\LogEntry;
15
16
define('__ROOT__', dirname(dirname(__FILE__)));
17
18
define('TABLE_PAGANTIS', 'pagantis');
19
define('TABLE_PAGANTIS_LOG', 'pagantis_log');
20
define('TABLE_PAGANTIS_CONFIG', 'pagantis_config');
21
define('TABLE_PAGANTIS_ORDERS', 'pagantis_orders');
22
define('TABLE_PAGANTIS_CONCURRENCY', 'pagantis_concurrency');
23
chdir('../../../../');
24
require('includes/application_top.php');
25
26
class pagantisNotify
27
{
28
    /** @var mixed $pagantisOrder */
29
    protected $pagantisOrder;
30
31
    /** @var $string $origin */
0 ignored issues
show
Documentation Bug introduced by
The doc comment $string at position 0 could not be parsed: Unknown type name '$string' at position 0 in $string.
Loading history...
32
    public $origin;
33
34
    /** @var $string */
0 ignored issues
show
Documentation Bug introduced by
The doc comment $string at position 0 could not be parsed: Unknown type name '$string' at position 0 in $string.
Loading history...
35
    public $order;
36
37
    /** @var mixed $oscommerceOrderId */
38
    protected $oscommerceOrderId = '';
39
40
    /** @var mixed $cfg */
41
    protected $cfg;
42
43
    /** @var Client $orderClient */
44
    protected $orderClient;
45
46
    /** @var Order $oscommerceOrder */
0 ignored issues
show
Bug introduced by
The type Order was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
47
    protected $oscommerceOrder;
48
49
    /** @var mixed $pagantisOrderId */
50
    protected $pagantisOrderId = '';
51
52
53
    /**
54
     * pagantisNotify constructor.
55
     */
56
    public function __construct()
57
    {
58
        $this->oscommerceOrderId = '7e93cd07dbeba82f6d77965f9bec2c7a';
59
        $this->getPagantisOrderId();
60
        $result = ($this->pagantisOrderId);
61
        $result = unserialize($result);
62
        foreach ($result as $var => $content) {
63
            $GLOBALS[$var] = unserialize($content);
64
            tep_session_register($var);
0 ignored issues
show
Bug introduced by
The function tep_session_register was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

64
            /** @scrutinizer ignore-call */ 
65
            tep_session_register($var);
Loading history...
65
        }
66
67
        header("Location: http://oscommerce-dev.docker:8095/checkout_process.php");
68
69
    }
70
71
    public static function __callStatic($name, $arguments)
72
    {
73
        // TODO: Implement __callStatic() method.
74
    }
75
76
    /**
77
     * Validation vs PagantisClient
78
     *
79
     * @return array|Array_
0 ignored issues
show
Bug introduced by
The type Array_ was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
80
     * @throws Exception
81
     */
82
    public function processInformation()
83
    {
84
        require_once(__ROOT__.'/pagantis/vendor/autoload.php');
85
        try {
86
            $this->checkConcurrency();
87
            $this->getMerchantOrder();
88
            $this->getPagantisOrderId();
89
            $this->getPagantisOrder();
90
            $this->checkOrderStatus();
91
            $this->checkMerchantOrderStatus();
92
            $this->validateAmount();
93
            $this->processMerchantOrder();
94
        } catch (\Exception $exception) {
95
            $jsonResponse = new JsonExceptionResponse();
96
            $jsonResponse->setMerchantOrderId($this->oscommerceOrderId);
97
            $jsonResponse->setPagantisOrderId($this->pagantisOrderId);
98
            $jsonResponse->setException($exception);
99
            $response = $jsonResponse->toJson();
100
            $this->insertLog($exception);
101
        }
102
        try {
103
            if (!isset($response)) {
104
                $this->confirmPagantisOrder();
105
                $jsonResponse = new JsonSuccessResponse();
106
                $jsonResponse->setMerchantOrderId($this->oscommerceOrderId);
107
                $jsonResponse->setPagantisOrderId($this->pagantisOrderId);
108
            }
109
        } catch (\Exception $exception) {
110
            $this->rollbackMerchantOrder();
111
            $jsonResponse = new JsonExceptionResponse();
112
            $jsonResponse->setMerchantOrderId($this->oscommerceOrderId);
113
            $jsonResponse->setPagantisOrderId($this->pagantisOrderId);
114
            $jsonResponse->setException($exception);
115
            $jsonResponse->toJson();
116
            $this->insertLog($exception);
117
        }
118
119
        if ($_SERVER['REQUEST_METHOD'] == 'POST') {
120
            $jsonResponse->printResponse();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $jsonResponse does not seem to be defined for all execution paths leading up to this point.
Loading history...
121
        } else {
122
            return $jsonResponse;
123
        }
124
    }
125
126
    /**
127
     * COMMON FUNCTIONS
128
     */
129
130
    /**
131
     * @throws Exception
132
     */
133
    private function checkConcurrency()
134
    {
135
        $this->getQuoteId();
136
        $this->checkConcurrencyTable();
137
        $this->unblockConcurrency();
138
        $this->blockConcurrency();
139
    }
140
141
    /**
142
     * @throws MerchantOrderNotFoundException
143
     */
144
    private function getMerchantOrder()
145
    {
146
        if (!isset($this->oscommerceOrder)) {
147
            throw new MerchantOrderNotFoundException();
148
        }
149
    }
150
151
    /**
152
     * @throws NoIdentificationException
153
     */
154
    private function getPagantisOrderId()
155
    {
156
        $query = "select pmt_order_id from ".TABLE_PAGANTIS_ORDERS." where os_order_id='".$this->oscommerceOrderId."'";
157
        $resultsSelect = tep_db_query($query);
0 ignored issues
show
Bug introduced by
The function tep_db_query was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

157
        $resultsSelect = /** @scrutinizer ignore-call */ tep_db_query($query);
Loading history...
158
        while ($orderRow = tep_db_fetch_array($resultsSelect)) {
0 ignored issues
show
Bug introduced by
The function tep_db_fetch_array was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

158
        while ($orderRow = /** @scrutinizer ignore-call */ tep_db_fetch_array($resultsSelect)) {
Loading history...
159
            $this->pagantisOrderId = $orderRow['pmt_order_id'];
160
        }
161
162
        if ($this->pagantisOrderId == '') {
163
            throw new NoIdentificationException();
164
        }
165
    }
166
167
    /**
168
     * @throws OrderNotFoundException
169
     */
170
    private function getPagantisOrder()
171
    {
172
        try {
173
            $publicKey     = trim(MODULE_PAYMENT_PAGANTIS_PK);
0 ignored issues
show
Bug introduced by
The constant MODULE_PAYMENT_PAGANTIS_PK was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
174
            $secretKey     = trim(MODULE_PAYMENT_PAGANTIS_SK);
0 ignored issues
show
Bug introduced by
The constant MODULE_PAYMENT_PAGANTIS_SK was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
175
            $this->orderClient   = new \Pagantis\OrdersApiClient\Client($publicKey, $secretKey);
176
            $this->pagantisOrder = $this->orderClient->getOrder($this->pagantisOrderId);
177
        } catch (\Exception $e) {
178
            throw new OrderNotFoundException();
179
        }
180
    }
181
182
    /**
183
     * @throws AlreadyProcessedException
184
     * @throws WrongStatusException
185
     */
186
    private function checkOrderStatus()
187
    {
188
        try {
189
            $this->checkPagantisStatus(array('AUTHORIZED'));
190
        } catch (\Exception $e) {
191
            if ($this->oscommerceOrderId!='') {
192
                throw new AlreadyProcessedException();
193
            } else {
194
                if ($this->pagantisOrder instanceof \Pagantis\OrdersApiClient\Model\Order) {
195
                    $status = $this->pagantisOrder->getStatus();
196
                } else {
197
                    $status = '-';
198
                }
199
                throw new WrongStatusException($status);
200
            }
201
        }
202
    }
203
204
    /**
205
     * @throws AlreadyProcessedException
206
     */
207
    private function checkMerchantOrderStatus()
208
    {
209
        if (!$this->oscommerceOrder->info['order_status']!=='1') {
0 ignored issues
show
introduced by
The condition ! $this->oscommerceOrder...'order_status'] !== '1' is always true.
Loading history...
210
            throw new AlreadyProcessedException();
211
        }
212
    }
213
214
    /**
215
     * @throws AmountMismatchException
216
     */
217
    private function validateAmount()
218
    {
219
        $pagantisAmount = $this->pagantisOrder->getShoppingCart()->getTotalAmount();
220
        $wcAmount = intval(strval(100 * $this->oscommerceOrder->get_total()));
221
        if ($pagantisAmount != $wcAmount) {
222
            throw new AmountMismatchException($pagantisAmount, $wcAmount);
223
        }
224
    }
225
226
    /**
227
     * @throws Exception
228
     */
229
    private function processMerchantOrder()
230
    {
231
        $this->saveOrder();
232
        $this->updateBdInfo();
233
    }
234
235
    /**
236
     * @return false|string
237
     * @throws UnknownException
238
     */
239
    private function confirmPagantisOrder()
240
    {
241
        try {
242
            $this->pagantisOrder = $this->orderClient->confirmOrder($this->pagantisOrderId);
243
        } catch (\Exception $e) {
244
            throw new UnknownException($e->getMessage());
245
        }
246
247
        $jsonResponse = new JsonSuccessResponse();
248
        return $jsonResponse->toJson();
249
    }
250
    /**
251
     * UTILS FUNCTIONS
252
     */
253
254
    /** STEP 1 CC - Check concurrency */
255
256
    /**
257
     * @throws QuoteNotFoundException
258
     */
259
    private function getQuoteId()
260
    {
261
        $this->oscommerceOrderId = $_GET['order_id'];
262
        if ($this->oscommerceOrderId == '') {
263
            throw new QuoteNotFoundException();
264
        }
265
    }
266
267
    /**
268
     * Check if concurrency table exists
269
     */
270
    private function checkConcurrencyTable()
271
    {
272
        $checkTable = tep_db_query("SHOW TABLES LIKE '".TABLE_PAGANTIS_CONCURRENCY."'");
0 ignored issues
show
Bug introduced by
The function tep_db_query was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

272
        $checkTable = /** @scrutinizer ignore-call */ tep_db_query("SHOW TABLES LIKE '".TABLE_PAGANTIS_CONCURRENCY."'");
Loading history...
273
        if (tep_db_num_rows($checkTable) == 0) {
0 ignored issues
show
Bug introduced by
The function tep_db_num_rows was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

273
        if (/** @scrutinizer ignore-call */ tep_db_num_rows($checkTable) == 0) {
Loading history...
274
            $sql = "CREATE TABLE IF NOT EXISTS ".TABLE_PAGANTIS_CONCURRENCY." (
275
                            id int NOT NULL,
276
                            `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
277
                            UNIQUE KEY id(id))";
278
            tep_db_query($sql);
279
        }
280
        return;
281
    }
282
283
    /**
284
     * Unlock the concurrency
285
     *
286
     * @param null $orderId
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $orderId is correct as it would always require null to be passed?
Loading history...
287
     * @throws Exception
288
     */
289
    private function unblockConcurrency($orderId = null)
290
    {
291
        try {
292
            if ($orderId == null) {
0 ignored issues
show
introduced by
The condition $orderId == null is always true.
Loading history...
293
                $query = "delete from ".TABLE_PAGANTIS_CONCURRENCY." where  timestamp<".(time() - 5);
294
                tep_db_query($query);
0 ignored issues
show
Bug introduced by
The function tep_db_query was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

294
                /** @scrutinizer ignore-call */ 
295
                tep_db_query($query);
Loading history...
295
            } elseif ($this->$orderId!='') {
296
                $query = "delete from ".TABLE_PAGANTIS_CONCURRENCY." where id=".$this->$orderId;
297
                tep_db_query($query);
298
            }
299
        } catch (Exception $exception) {
300
            throw new ConcurrencyException();
0 ignored issues
show
Bug introduced by
The type ConcurrencyException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
301
        }
302
    }
303
304
    /**
305
     * @throws \Exception
306
     */
307
    private function blockConcurrency()
308
    {
309
        try {
310
            $query = "INSERT INTO ".TABLE_PAGANTIS_CONCURRENCY." (id) VALUES ('$this->oscommerceOrderId')";
311
            tep_db_query($query);
0 ignored issues
show
Bug introduced by
The function tep_db_query was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

311
            /** @scrutinizer ignore-call */ 
312
            tep_db_query($query);
Loading history...
312
        } catch (Exception $exception) {
313
            throw new ConcurrencyException();
314
        }
315
    }
316
317
    /** STEP 2 GMO - Get Merchant Order */
318
    /** STEP 3 GPOI - Get Pagantis OrderId */
319
    /** STEP 4 GPO - Get Pagantis Order */
320
    /** STEP 5 COS - Check Order Status */
321
    /**
322
     * @param $statusArray
323
     *
324
     * @throws \Exception
325
     */
326
    private function checkPagantisStatus($statusArray)
327
    {
328
        $pagantisStatus = array();
329
        foreach ($statusArray as $status) {
330
            $pagantisStatus[] = constant("\Pagantis\OrdersApiClient\Model\Order::STATUS_$status");
331
        }
332
333
        if ($this->pagantisOrder instanceof \Pagantis\OrdersApiClient\Model\Order) {
334
            $payed = in_array($this->pagantisOrder->getStatus(), $pagantisStatus);
335
            if (!$payed) {
336
                if ($this->pagantisOrder instanceof \Pagantis\OrdersApiClient\Model\Order) {
0 ignored issues
show
introduced by
$this->pagantisOrder is always a sub-type of Pagantis\OrdersApiClient\Model\Order.
Loading history...
337
                    $status = $this->pagantisOrder->getStatus();
338
                } else {
339
                    $status = '-';
340
                }
341
                throw new WrongStatusException($status);
342
            }
343
        } else {
344
            throw new OrderNotFoundException();
345
        }
346
    }
347
    /** STEP 6 CMOS - Check Merchant Order Status */
348
    /** STEP 7 VA - Validate Amount */
349
    /** STEP 8 PMO - Process Merchant Order */
350
    /**
351
     * @throws \Exception
352
     */
353
    private function saveOrder()
354
    {
355
        global $oscommerce;
356
        $paymentResult = $this->oscommerceOrder->payment_complete();
357
        if ($paymentResult) {
358
            $this->oscommerceOrder->add_order_note("Notification received via $this->origin");
359
            $this->oscommerceOrder->reduce_order_stock();
360
            $this->oscommerceOrder->save();
361
362
            $oscommerce->cart->empty_cart();
363
            sleep(3);
364
        } else {
365
            throw new UnknownException('Order can not be saved');
366
        }
367
    }
368
369
    /**
370
     * Save the merchant order_id with the related identification
371
     */
372
    private function updateBdInfo()
373
    {
374
        global $wpdb;
375
376
        $this->checkDbTable();
0 ignored issues
show
Bug introduced by
The method checkDbTable() does not exist on pagantisNotify. ( Ignorable by Annotation )

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

376
        $this->/** @scrutinizer ignore-call */ 
377
               checkDbTable();

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...
377
        $tableName = $wpdb->prefix.self::ORDERS_TABLE;
0 ignored issues
show
Bug introduced by
The constant pagantisNotify::ORDERS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
378
379
        $wpdb->update(
380
            $tableName,
381
            array('wc_order_id'=>$this->oscommerceOrderId),
382
            array('id' => $this->oscommerceOrderId),
383
            array('%s'),
384
            array('%d')
385
        );
386
    }
387
388
    /** STEP 9 CPO - Confirmation Pagantis Order */
389
    private function rollbackMerchantOrder()
390
    {
391
        $this->oscommerceOrder->update_status('pending', __('Pending payment', 'oscommerce'));
0 ignored issues
show
Bug introduced by
The function __ was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

391
        $this->oscommerceOrder->update_status('pending', /** @scrutinizer ignore-call */ __('Pending payment', 'oscommerce'));
Loading history...
392
    }
393
394
    /**
395
     * @param $exceptionMessage
396
     *
397
     * @throws \Zend_Db_Exception
398
     */
399
    private function insertLog($exception)
400
    {
401
        global $wpdb;
402
403
        if ($exception instanceof \Exception) {
404
            $this->checkDbLogTable();
0 ignored issues
show
Bug introduced by
The method checkDbLogTable() does not exist on pagantisNotify. ( Ignorable by Annotation )

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

404
            $this->/** @scrutinizer ignore-call */ 
405
                   checkDbLogTable();

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...
405
            $logEntry= new LogEntry();
406
            $logEntryJson = $logEntry->error($exception)->toJson();
407
408
            $tableName = $wpdb->prefix.self::LOGS_TABLE;
0 ignored issues
show
Bug introduced by
The constant pagantisNotify::LOGS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
409
            $wpdb->insert($tableName, array('log' => $logEntryJson));
410
        }
411
    }
412
}
413
414
$pgNotify = new pagantisNotify();
415
$pgNotify->processInformation();