GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 1ead01...143819 )
by Shaxzodbek
01:29
created

Payme   F

Complexity

Total Complexity 60

Size/Duplication

Total Lines 447
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 7

Importance

Changes 0
Metric Value
wmc 60
lcom 1
cbo 7
dl 0
loc 447
rs 3.6
c 0
b 0
f 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
B run() 0 40 8
A CheckPerformTransaction() 0 31 5
A CheckTransaction() 0 20 4
A validateParams() 0 18 3
B CreateTransaction() 0 73 8
B PerformTransaction() 0 61 5
B CancelTransaction() 0 67 7
A findTransactionByParams() 0 5 1
A getModelTransactions() 0 9 2
B ChangePassword() 0 28 7
A GetStatement() 0 23 4
A getReport() 0 35 4
A getRedirectParams() 0 12 1

How to fix   Complexity   

Complex Class

Complex classes like Payme 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 Payme, and based on these observations, apply Extract Interface, too.

1
<?php
2
namespace Goodoneuz\PayUz\Http\Classes\Payme;
3
4
use Goodoneuz\PayUz\Models\Transaction;
5
use Goodoneuz\PayUz\Models\PaymentSystem;
6
use Goodoneuz\PayUz\Services\PaymentService;
7
use Goodoneuz\PayUz\Http\Classes\DataFormat;
8
use Goodoneuz\PayUz\Http\Classes\BaseGateway;
9
use Goodoneuz\PayUz\Models\PaymentSystemParam;
10
use Goodoneuz\PayUz\Http\Classes\PaymentException;
11
use Goodoneuz\PayUz\Services\PaymentSystemService;
12
13
class Payme {
14
    public $config;
15
    public $request;
16
    public $response;
17
    public $merchant;
18
    public $payment_system;
19
20
    /**
21
     * Payme constructor.
22
     */
23
    public function __construct()
24
    {
25
        $this->config   = PaymentSystemService::getPaymentSystemParamsCollect(PaymentSystem::PAYME);
26
    }
27
28
    public function run()
29
    {
30
        $this->response = new Response();
31
        $this->request  = new Request($this->response);
32
        $this->response->setRequest($this->request);
33
        $this->merchant = new Merchant($this->config, $this->response);
34
        // authorize session
35
        $this->merchant->Authorize();
36
37
        // handle request
38
        switch ($this->request->method) {
39
            case 'CheckPerformTransaction':
40
                $this->CheckPerformTransaction();
41
                break;
42
            case 'CheckTransaction':
43
                $this->CheckTransaction();
44
                break;
45
            case 'CreateTransaction':
46
                $this->CreateTransaction();
47
                break;
48
            case 'PerformTransaction':
49
                $this->PerformTransaction();
50
                break;
51
            case 'CancelTransaction':
52
                $this->CancelTransaction();
53
                break;
54
            case 'ChangePassword':
55
                $this->ChangePassword();
56
                break;
57
            case 'GetStatement':
58
                $this->GetStatement();
59
                break;
60
            default:
61
                $this->response->error(
62
                    Response::ERROR_METHOD_NOT_FOUND,
63
                    'Method not found.',
64
                    $this->request->method
65
                );
66
        }
67
    }
68
    
69
    private function CheckPerformTransaction()
70
    {
71
        $this->validateParams($this->request->params);
72
        $model = PaymentService::convertKeyToModel($this->request->params['account'][$this->config['key']]);
73
        if ($model == null){
74
            $this->response->error(
75
                Response::ERROR_INVALID_ACCOUNT,
76
                'Object not fount.'
77
            );
78
        }
79
        if (!PaymentService::isProperModelAndAmount($model, $this->request->params['amount'])){
80
            $this->response->error(
81
                Response::ERROR_INVALID_AMOUNT,
82
                'Invalid amount for this object.'
83
            );
84
        }
85
        $active_transactions = $this->getModelTransactions($model, true);
86
        \Log::info([
87
            'active transactions' => count($active_transactions),
88
            'multi' => config('payuz')['multi_transaction']
89
        ]);
90
        if ((count($active_transactions) > 0) && (config('payuz')['multi_transaction'] == false)){
91
            $this->response->error(
92
                Response::ERROR_INVALID_TRANSACTION,
93
                'There is other active/completed transaction for this object.'
94
            );
95
        }
96
        PaymentService::payListener($model,null,'before-pay');
97
        
98
        $this->response->success(['allow' => true]);
99
    }
100
    private function CheckTransaction()
101
    {
102
        $transaction  =  $this->findTransactionByParams($this->request->params);
103
        if (!$transaction) {
104
            $this->response->error(
105
                Response::ERROR_TRANSACTION_NOT_FOUND,
106
                'Transaction not found.'
107
            );
108
        }
109
110
        $detail = json_decode($transaction->detail,true);
111
        $this->response->success([
112
            'create_time'  => 1*$detail['create_time'],
113
            'perform_time' => 1*$detail['perform_time'],
114
            'cancel_time'  => 1*$detail['cancel_time'],
115
            'transaction'  => (string)$transaction->id,
116
            'state'        => 1*$transaction->state,
117
            'reason'       => ($transaction->comment && is_numeric($transaction->comment)) ? 1 * $transaction->comment : null,
118
        ]);
119
    }
120
121
    public function validateParams(array $params)
122
    {
123
        // for example, check amount is numeric
124
        if (!is_numeric($params['amount'])) {
125
            $this->response->error( Response::ERROR_INVALID_AMOUNT, 'Incorrect amount.');
126
        }
127
128
        // assume, we should have order_id
129
        if (!isset($params['account'][$this->config['key']])) {
130
            $this->response->error(
131
                Response::ERROR_INVALID_ACCOUNT,
132
                Response::message( 'Неверный код Счет.', 'Billing kodida xatolik.', 'Incorrect object code.'),
133
                'key'
134
            );
135
        }
136
137
        return true;
138
    }
139
    private function CreateTransaction()
140
    {
141
142
        $this->validateParams($this->request->params);
143
        $model = PaymentService::convertKeyToModel($this->request->params['account'][$this->config['key']]);
144
        //todo alert if model is null
145
        $transaction = $this->findTransactionByParams($this->request->params);
146
        if ($transaction) {
147
            if ($transaction->state != Transaction::STATE_CREATED) {
148
                $this->response->error(
149
                    Response::ERROR_COULD_NOT_PERFORM,
150
                    'Transaction found, but is not active.'
151
                );
152
            } elseif ($transaction->isExpired()) {
153
                $transaction->cancel(Transaction::REASON_CANCELLED_BY_TIMEOUT);
154
                $this->response->error(
155
                    Response::ERROR_COULD_NOT_PERFORM,
156
                    'Transaction is expired.'
157
                );
158
            }
159
        } else {
160
161
            try{
162
                $this->CheckPerformTransaction();
163
            } catch(PaymentException $e){
164
                if ($e->response->response['error'] != null)
165
                throw $e;
166
            }
167
168
            if (DataFormat::timestamp2milliseconds(1 * $this->request->params['time']) - DataFormat::timestamp(true) >= Transaction::TIMEOUT) {
169
                $this->response->error(
170
                    Response::ERROR_INVALID_ACCOUNT,
171
                    Response::message(
172
                        'С даты создания транзакции прошло ' . Transaction::TIMEOUT . 'мс',
173
                        'Tranzaksiya yaratilgan vaqtdan ' . Transaction::TIMEOUT . 'ms o`tgan',
174
                        'Since create time of the transaction passed ' . Transaction::TIMEOUT . 'ms'
175
                    ),
176
                    'time'
177
                );
178
            }
179
180
            $create_time = DataFormat::timestamp(true);
181
182
            $detail = json_encode(array(
183
                'create_time'           => $create_time,
184
                'perform_time'          => null,
185
                'cancel_time'           => null,
186
                'system_time_datetime'  => DataFormat::timestamp2datetime($this->request->params['time'])
187
            ));
188
189
            $transaction = Transaction::create([
0 ignored issues
show
Bug introduced by
The method create() does not exist on Goodoneuz\PayUz\Models\Transaction. Did you maybe mean created()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
190
                'payment_system'        => PaymentSystem::PAYME,
191
                'system_transaction_id' => $this->request->params['id'],
192
                'amount'                =>1*($this->request->amount)/100,
193
                'currency_code'         => Transaction::CURRENCY_CODE_UZS,
194
                'state'                 => Transaction::STATE_CREATED,
195
                'updated_time'          => 1*$create_time,
196
                'comment'               => (isset($this->request->params['error_note'])?$this->request->params['error_note']:''),
197
                'detail'                => $detail,
198
                'transactionable_type'  => get_class($model),
199
                'transactionable_id'    => $model->id
200
            ]);
201
        }
202
         
203
        PaymentService::payListener($model,$transaction,'paying');
204
        
205
        $this->response->success([
206
            'create_time' => 1*$transaction->updated_time,
207
            'transaction' => (string)$transaction->id,
208
            'state'       => 1*$transaction->state,
209
            'receivers'   => $transaction->receivers,
210
        ]);
211
    }
212
213
    private function PerformTransaction()
214
    {
215
        $transaction = $this->findTransactionByParams($this->request->params);
216
217
        // if transaction not found, send error
218
        if (!$transaction) {
219
            $this->response->error(Response::ERROR_TRANSACTION_NOT_FOUND, 'Transaction not found.');
220
        }
221
222
        switch ($transaction->state) {
223
            case Transaction::STATE_CREATED:
224
                if ($transaction->isExpired()) {
225
                    $transaction->cancel(Transaction::REASON_CANCELLED_BY_TIMEOUT);
226
                    $this->response->error(
227
                        Response::ERROR_COULD_NOT_PERFORM,
228
                        'Transaction is expired.'
229
                    );
230
                } else {
231
232
                    $perform_time               = DataFormat::timestamp(true);
233
                    $transaction->state         = Transaction::STATE_COMPLETED;
234
                    $transaction->updated_time  = $perform_time;
235
236
                    $detail = json_decode($transaction->detail,true);
237
                    $detail['perform_time']   =   $perform_time;
238
                    $detail = json_encode($detail);
239
240
                    $transaction->detail = $detail;
241
242
                    $transaction->update();
243
244
                    PaymentService::payListener(null,$transaction,'after-pay');
245
246
                    $this->response->success([
247
                        'transaction'  => (string)$transaction->id,
248
                        'perform_time' => 1*$perform_time,
249
                        'state'        => 1*$transaction->state,
250
                    ]);
251
                }
252
                break;
253
254
            case Transaction::STATE_COMPLETED: // handle complete transaction
255
                $detail = json_decode($transaction->detail,true);
256
                
257
                $this->response->success([
258
                    'transaction'  => (string)$transaction->id,
259
                    'perform_time' => 1*$detail['perform_time'],
260
                    'state'        => 1*$transaction->state,
261
                ]);
262
            
263
                break;
264
265
            default:
266
                // unknown situation
267
                $this->response->error(
268
                    Response::ERROR_COULD_NOT_PERFORM,
269
                    'Could not perform this operation.'
270
                );
271
                break;
272
        }
273
    }
274
    private function CancelTransaction()
275
    {
276
        $transaction = $this->findTransactionByParams($this->request->params);
277
278
        // if transaction not found, send error
279
        if (!$transaction) {
280
            $this->response->error(Response::ERROR_TRANSACTION_NOT_FOUND, 'Transaction not found.');
281
        }
282
283
        switch ($transaction->state) {
284
            // if already cancelled, just send it
285
            case Transaction::STATE_CANCELLED:
286
            case Transaction::STATE_CANCELLED_AFTER_COMPLETE:
287
                $detail = json_decode($transaction->detail,true);
288
                $this->response->success([
289
                    'transaction' => (string)$transaction->id,
290
                    'cancel_time' => 1*$detail['cancel_time'],
291
                    'state'       => 1*$transaction->state,
292
                ]);
293
                break;
294
295
            // cancel active transaction
296
            case Transaction::STATE_CREATED:
297
                // cancel transaction with given reason
298
                $transaction->cancel(1 * $this->request->params['reason']);
299
                
300
                $cancel_time               = DataFormat::timestamp(true);
301
                
302
                $detail = json_decode($transaction->detail,true);
303
                $detail['cancel_time']   =   $cancel_time;
304
                
305
                $transaction->update([
306
                    'updated_time'=> $cancel_time,
307
                    'detail' => json_encode($detail)]);
308
309
310
                PaymentService::payListener(null,$transaction,'cancel-pay');
311
312
                $this->response->success([
313
                    'transaction' => (string)$transaction->id,
314
                    'cancel_time' => 1*$cancel_time,
315
                    'state'       => 1*$transaction->state,
316
                ]);
317
                break;
318
319
            case Transaction::STATE_COMPLETED:
320
                if (true) {
321
                    $transaction->cancel(1 * $this->request->params['reason']);
322
323
                    $detail = json_decode($transaction->detail,true);
324
325
                    PaymentService::payListener(null,$transaction,'cancel-pay');
326
327
                    $this->response->success([
328
                        'transaction' => (string)$transaction->id,
329
                        'cancel_time' => 1*$detail['cancel_time'],
330
                        'state'       => 1*$transaction->state,
331
                    ]);
332
                } else {
333
                    $this->response->error(
334
                        Response::ERROR_COULD_NOT_CANCEL,
335
                        'Could not cancel transaction. Order is delivered/Service is completed.'
336
                    );
337
                }
338
                break;
339
        }
340
    }
341
342
    public function findTransactionByParams($params)
343
    {
344
        $transaction = Transaction::where('payment_system', PaymentSystem::PAYME)->where('system_transaction_id', $params['id'])->first();
345
        return $transaction;  
346
    }
347
    public function getModelTransactions($model, $active = false)
348
    {
349
        $transactions = Transaction::where('payment_system', PaymentSystem::PAYME)
350
        ->where('transactionable_type',get_class($model))
351
        ->where('transactionable_id',$model->id);
352
        if ($active)
353
            $transactions = $transactions->where('state', Transaction::STATE_CREATED);
354
        return $transactions->get();  
355
    }
356
357
    /**
358
     * @throws \Goodoneuz\PayUz\Http\Classes\PaymentException
359
     */
360
    private function ChangePassword()
361
    {
362
        // validate, password is specified, otherwise send error
363
        if (!isset($this->request->params['password']) || !trim($this->request->params['password'])) {
364
            $this->response->error(Response::ERROR_INVALID_ACCOUNT, 'New password not specified.', 'password');
365
        }
366
367
        // if current password specified as new, then send error
368
        if ($this->merchant->config['password'] == $this->request->params['password']) {
369
            $this->response->error(Response::ERROR_INSUFFICIENT_PRIVILEGE, 'Insufficient privilege. Incorrect new password.');
370
        }
371
372
        $completed = false;
373
        $params = PaymentSystemParam::where('system',PaymentSystem::PAYME)->get();
374
        foreach($params as $param){
375
            if($param->name == 'password'){
376
                $param->update([
377
                    'value' =>  $this->request->params['password']
378
                ]);
379
                $completed = true;
380
            }
381
        }
382
        if (!$completed){
383
            $this->response->error(Response::ERROR_INTERNAL_SYSTEM, 'Internal System Error.');
384
        }
385
386
        $this->response->success(['success' => true]);
387
    }
388
389
    private function GetStatement()
390
    {
391
        // validate 'from'
392
        if (!isset($this->request->params['from'])) {
393
            $this->response->error(Response::ERROR_INVALID_ACCOUNT, 'Incorrect period.', 'from');
394
        }
395
396
        // validate 'to'
397
        if (!isset($this->request->params['to'])) {
398
            $this->response->error(Response::ERROR_INVALID_ACCOUNT, 'Incorrect period.', 'to');
399
        }
400
401
        // validate period
402
        if (1 * $this->request->params['from'] >= 1 * $this->request->params['to']) {
403
            $this->response->error(Response::ERROR_INVALID_ACCOUNT, 'Incorrect period. (from >= to)', 'from');
404
        }
405
406
        // get list of transactions for specified period
407
        $transactions  = $this->getReport($this->request->params['from'], $this->request->params['to']);
408
409
        // send results back
410
        $this->response->success(['transactions' => $transactions]);
411
    }
412
    public function getReport($from_date, $to_date)
413
    {
414
        $from_date = DataFormat::timestamp2datetime($from_date);
415
        $to_date   = DataFormat::timestamp2datetime($to_date);
416
417
        $transactions = Transaction::where('payment_system',PaymentSystem::PAYME)
418
            ->where('state',Transaction::STATE_COMPLETED)
419
            ->where('created_at','>=',$from_date)
420
            ->where('created_at','<=',$to_date)->get();
421
        // assume, here we have $rows variable that is populated with transactions from data store
422
        // normalize data for response
423
        $result = [];
424
        foreach ($transactions as $row) {
425
            $detail = json_decode($row['detail'],true);
426
427
            $result[] = [
428
                'id'           => (string)$row['system_transaction_id'], // paycom transaction id
429
                'time'         => 1 * $detail['system_time_datetime'], // paycom transaction timestamp as is
430
                'amount'       => 1 * $row['amount'],
431
                'account'      => [
432
                    'key' => 1 * $row[$this->config['key']], // account parameters to identify client/order/service
433
                    // ... additional parameters may be listed here, which are belongs to the account
434
                ],
435
                'create_time'  => DataFormat::datetime2timestamp($detail['create_time']),
436
                'perform_time' => DataFormat::datetime2timestamp($detail['perform_time']),
437
                'cancel_time'  => DataFormat::datetime2timestamp($detail['cancel_time']),
438
                'transaction'  => (string)$row['id'],
439
                'state'        => 1 * $row['state'],
440
                'reason'       => isset($row['comment']) ? 1 * $row['comment'] : null,
441
                'receivers'    => isset($row['receivers']) ? json_decode($row['receivers'], true) : null,
442
            ];
443
        }
444
        return $result;
445
446
    }
447
    public function getRedirectParams($model, $amount, $currency, $url){
448
        return [
449
            'merchant' => $this->config['merchant_id'],
450
            'amount' => $amount*100,
451
            'account[key]' => PaymentService::convertModelToKey($model),
452
            'lang' => 'ru',
453
            'currency' => $currency,
454
            'callback' => $url,
455
            'callback_timeout' => 20000,
456
            'url'   => "https://checkout.paycom.uz/",
457
        ];
458
    }
459
}
460