Test Failed
Push — trunk ( 30e273...8e4860 )
by SuperNova.WS
14:08
created

sn_module_payment::debug()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 6
ccs 0
cts 5
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
3
use DBAL\db_mysql;
4
use Modules\sn_module;
5
6
/**
7
 * User: Gorlum
8
 * Date: 21.04.2015
9
 * Time: 3:49
10
 */
11
abstract class sn_module_payment extends sn_module {
12
  const DO_NOT_REDIRECT = 'DO_NOT_REDIRECT';
13
  public $versionCommitted = '#44a104#';
14
15
  public $active = false;
16
17
  public static $bonus_table = [
18
    2000    => 0,
19
    // 5000 => 0,
20
    10000   => 0,
21
    20000   => 0,
22
    50000   => 0.02,
23
    100000  => 0.05,
24
    200000  => 0.07,
25
    300000  => 0.10,
26
    400000  => 0.15,
27
    500000  => 0.20,
28
    800000  => 0.25,
29
    1000000 => 0.30,
30
    1500000 => 0.40,
31
    2000000 => 0.50,
32
    3000000 => 0.60,
33
    5000000 => 0.70,
34
  ];
35
36
  public static $payment_methods = [
37
    PAYMENT_METHOD_BANK_CARD => [
38
      /*
39
      PAYMENT_METHOD_id => array(
40
        'currency' => 'WMR', // Currency code 3 letter
41
        'image' => 'design/images/payments/emoney/webmoney.png', // Optional - image location from root. Setting image disables buttoning and name printing
42
        'name' => true, // Optional. Forces method name printing with 'image' set
43
        'button' => true, // Optional. Forces method buttoning with 'image' set
44
      ),
45
      */
46
      PAYMENT_METHOD_BANK_CARD_STANDARD         => [
47
        'currency' => 'RUB',
48
        'image'    => 'design/images/payments/card/generic.png',
49
        'button'   => true,
50
      ],
51
      PAYMENT_METHOD_BANK_CARD_LIQPAY           => [
52
        'currency' => 'UAH',
53
        'image'    => 'design/images/payments/card/liqpay.png',
54
        'button'   => true,
55
      ],
56
      PAYMENT_METHOD_BANK_CARD_EASYPAY          => [
57
        'currency' => 'UAH',
58
        'image'    => 'design/images/payments/card/easypay.png',
59
        'button'   => true,
60
      ],
61
      PAYMENT_METHOD_BANK_CARD_AMERICAN_EXPRESS => [
62
        'currency' => 'USD',
63
        'image'    => 'design/images/payments/card/american_express.png',
64
        'button'   => true,
65
      ],
66
      PAYMENT_METHOD_BANK_CARD_JCB              => [
67
        'currency' => 'USD',
68
        'image'    => 'design/images/payments/card/jcb.png',
69
        'button'   => true,
70
      ],
71
      PAYMENT_METHOD_BANK_CARD_UNIONPAY         => [
72
        'currency' => 'USD',
73
        'image'    => 'design/images/payments/card/unionpay.png',
74
        'button'   => true,
75
      ],
76
    ],
77
78
    PAYMENT_METHOD_EMONEY => [
79
      PAYMENT_METHOD_EMONEY_YANDEX       => [
80
        'currency' => 'RUB',
81
        'image'    => 'design/images/payments/emoney/yandexmoney.png',
82
        'button'   => true,
83
      ],
84
      PAYMENT_METHOD_EMONEY_QIWI         => [
85
        'currency' => 'RUB',
86
        'image'    => 'design/images/payments/emoney/qiwi.png',
87
        'button'   => true,
88
      ],
89
      PAYMENT_METHOD_EMONEY_PAYPAL       => [
90
        'currency' => 'RUB',
91
        'image'    => 'design/images/payments/emoney/paypal.png',
92
        'button'   => true,
93
      ],
94
      PAYMENT_METHOD_EMONEY_WEBMONEY_WMR => [
95
//        'currency' => 'WMR',
96
        'currency' => 'RUB',
97
        'image'    => 'design/images/payments/emoney/webmoney_wmr.gif',
98
        'button'   => true,
99
      ],
100
      PAYMENT_METHOD_EMONEY_WEBMONEY_WMZ => [
101
//        'currency' => 'WMZ',
102
        'currency' => 'RUB',
103
        'image'    => 'design/images/payments/emoney/webmoney_wmz.gif',
104
        'button'   => true,
105
      ],
106
      PAYMENT_METHOD_EMONEY_WEBMONEY_WMU => [
107
//        'currency' => 'WMU',
108
        'currency' => 'RUB',
109
        'image'    => 'design/images/payments/emoney/webmoney_wmu.gif',
110
        'button'   => true,
111
      ],
112
      PAYMENT_METHOD_EMONEY_WEBMONEY_WME => [
113
//        'currency' => 'WME',
114
        'currency' => 'RUB',
115
        'image'    => 'design/images/payments/emoney/webmoney_wme.gif',
116
        'button'   => true,
117
      ],
118
      PAYMENT_METHOD_EMONEY_WEBMONEY_WMB => [
119
//        'currency' => 'WMB',
120
        'currency' => 'RUB',
121
        'image'    => 'design/images/payments/emoney/webmoney_wmb.gif',
122
        'button'   => true,
123
      ],
124
      PAYMENT_METHOD_EMONEY_TELEMONEY    => [
125
        'currency' => 'RUB',
126
        'image'    => 'design/images/payments/emoney/telemoney.gif',
127
        'button'   => true,
128
      ],
129
      PAYMENT_METHOD_EMONEY_ELECSNET     => [
130
        'currency' => 'RUB',
131
        'image'    => 'design/images/payments/emoney/elecsnet.png',
132
        'button'   => true,
133
      ],
134
      PAYMENT_METHOD_EMONEY_EASYPAY      => [
135
        'currency' => 'RUB',
136
        'image'    => 'design/images/payments/emoney/easypay.png',
137
        'button'   => true,
138
      ],
139
      PAYMENT_METHOD_EMONEY_RUR_W1R      => [
140
        'currency' => 'RUB',
141
        'image'    => 'design/images/payments/emoney/walletone.png',
142
        'button'   => true,
143
      ],
144
      PAYMENT_METHOD_EMONEY_MAILRU       => [
145
        'currency' => 'RUB',
146
        'image'    => 'design/images/payments/emoney/mailru.gif',
147
      ],
148
    ],
149
150
    PAYMENT_METHOD_MOBILE => [
151
      PAYMENT_METHOD_MOBILE_SMS         => [
152
        'currency' => 'RUB',
153
        'image'    => 'design/images/payments/mobile/sms.png',
154
        'name'     => true,
155
        'button'   => true,
156
      ],
157
      PAYMENT_METHOD_MOBILE_PAYPAL_ZONG => [
158
        'currency' => 'USD',
159
        'image'    => 'design/images/payments/mobile/paypal_zong.png',
160
        'name'     => true,
161
        'button'   => true,
162
      ],
163
      PAYMENT_METHOD_MOBILE_XSOLLA      => [
164
        'currency' => 'RUB',
165
        'image'    => 'design/images/payments/mobile/xsolla.png',
166
        'name'     => true,
167
        'button'   => true,
168
      ],
169
170
171
      PAYMENT_METHOD_MOBILE_MEGAPHONE => [
172
        'currency' => 'RUB',
173
        'image'    => 'design/images/payments/mobile/megafon.png',
174
        'button'   => true,
175
      ],
176
      PAYMENT_METHOD_MOBILE_MTS       => [
177
        'currency' => 'RUB',
178
        'image'    => 'design/images/payments/mobile/mts.png',
179
        'button'   => true,
180
      ],
181
      PAYMENT_METHOD_MOBILE_KYIVSTAR  => [
182
        'currency' => 'UAH',
183
        'image'    => 'design/images/payments/mobile/kyivstar.png',
184
        'button'   => true,
185
      ],
186
    ],
187
188
    PAYMENT_METHOD_BANK_INTERNET => [
189
      PAYMENT_METHOD_BANK_INTERNET_PRIVAT24         => [
190
        'currency' => 'UAH',
191
        'image'    => 'design/images/payments/bank_internet/privat24.png',
192
        'button'   => true,
193
      ],
194
      PAYMENT_METHOD_BANK_INTERNET_BANK24           => [
195
        'currency' => 'UAH',
196
        'image'    => 'design/images/payments/bank_internet/bank24.png',
197
        'button'   => true,
198
      ],
199
      PAYMENT_METHOD_BANK_INTERNET_ALFA_BANK        => [
200
        'currency' => 'RUB',
201
        'image'    => 'design/images/payments/bank_internet/alfa_bank.png',
202
        'button'   => true,
203
      ],
204
      PAYMENT_METHOD_BANK_INTERNET_SBERBANK         => [
205
        'currency' => 'RUB',
206
        'image'    => 'design/images/payments/bank_internet/sberbank.png',
207
        'button'   => true,
208
      ],
209
      PAYMENT_METHOD_BANK_INTERNET_PROSMVYAZBANK    => [
210
        'currency' => 'RUB',
211
        'image'    => 'design/images/payments/bank_internet/prosmvyazbank.png',
212
        'button'   => true,
213
      ],
214
      PAYMENT_METHOD_BANK_INTERNET_HANDY_BANK       => [
215
        'currency' => 'RUB',
216
        'image'    => 'design/images/payments/bank_internet/handy_bank.png',
217
        'button'   => true,
218
      ],
219
      PAYMENT_METHOD_BANK_INTERNET_RUSSKIY_STANDART => [
220
        'currency' => 'RUB',
221
        'image'    => 'design/images/payments/bank_internet/russkiy_standart.gif',
222
      ],
223
      PAYMENT_METHOD_BANK_INTERNET_VTB24            => [
224
        'currency' => 'RUB',
225
        'image'    => 'design/images/payments/bank_internet/vtb24.gif',
226
      ],
227
      PAYMENT_METHOD_BANK_INTERNET_OCEAN_BANK       => [
228
        'currency' => 'RUB',
229
        'image'    => 'design/images/payments/bank_internet/ocean_bank.gif',
230
      ],
231
      PAYMENT_METHOD_BANK_INTERNET_007              => [
232
        'currency' => 'RUB',
233
      ],
234
      PAYMENT_METHOD_BANK_INTERNET_008              => [
235
        'currency' => 'RUB',
236
      ],
237
      PAYMENT_METHOD_BANK_INTERNET_009              => [
238
        'currency' => 'RUB',
239
      ],
240
      PAYMENT_METHOD_BANK_INTERNET_010              => [
241
        'currency' => 'RUB',
242
      ],
243
      PAYMENT_METHOD_BANK_INTERNET_011              => [
244
        'currency' => 'RUB',
245
      ],
246
      PAYMENT_METHOD_BANK_INTERNET_012              => [
247
        'currency' => 'RUB',
248
      ],
249
      PAYMENT_METHOD_BANK_INTERNET_013              => [
250
        'currency' => 'RUB',
251
      ],
252
      PAYMENT_METHOD_BANK_INTERNET_014              => [
253
        'currency' => 'RUB',
254
      ],
255
      PAYMENT_METHOD_BANK_INTERNET_015              => [
256
        'currency' => 'RUB',
257
      ],
258
      PAYMENT_METHOD_BANK_INTERNET_016              => [
259
        'currency' => 'RUB',
260
      ],
261
      PAYMENT_METHOD_BANK_INTERNET_017              => [
262
        'currency' => 'RUB',
263
      ],
264
      PAYMENT_METHOD_BANK_INTERNET_018              => [
265
        'currency' => 'RUB',
266
      ],
267
      PAYMENT_METHOD_BANK_INTERNET_019              => [
268
        'currency' => 'RUB',
269
      ],
270
      PAYMENT_METHOD_BANK_INTERNET_020              => [
271
        'currency' => 'RUB',
272
      ],
273
      PAYMENT_METHOD_BANK_INTERNET_021              => [
274
        'currency' => 'RUB',
275
      ],
276
    ],
277
278
    PAYMENT_METHOD_BANK_TRANSFER => [],
279
280
    PAYMENT_METHOD_TERMINAL => [
281
      PAYMENT_METHOD_TERMINAL_UKRAINE    => [
282
        'currency' => 'UAH',
283
        'image'    => 'design/images/payments/terminal/ukraine.png',
284
        'button'   => true,
285
        'name'     => true,
286
      ],
287
      PAYMENT_METHOD_TERMINAL_IBOX       => [
288
        'currency' => 'UAH',
289
        'image'    => 'design/images/payments/terminal/ibox.png',
290
        'button'   => true,
291
      ],
292
      PAYMENT_METHOD_TERMINAL_EASYPAY    => [
293
        'currency' => 'UAH',
294
        'image'    => 'design/images/payments/terminal/easypay.png',
295
        'button'   => true,
296
      ],
297
      PAYMENT_METHOD_TERMINAL_RUSSIA     => [
298
        'currency' => 'RUB',
299
        'image'    => 'design/images/payments/terminal/russia.png',
300
        'button'   => true,
301
        'name'     => true,
302
      ],
303
      PAYMENT_METHOD_TERMINAL_QIWI       => [
304
        'currency' => 'RUB',
305
        'image'    => 'design/images/payments/terminal/qiwi.png',
306
        'button'   => true,
307
      ],
308
      PAYMENT_METHOD_TERMINAL_ELECSNET   => [
309
        'currency' => 'RUB',
310
        'image'    => 'design/images/payments/terminal/elecsnet.png',
311
        'button'   => true,
312
      ],
313
      PAYMENT_METHOD_TERMINAL_TELEPAY    => [
314
        'currency' => 'RUB',
315
        'image'    => 'design/images/payments/terminal/telepay.png',
316
        'button'   => true,
317
      ],
318
      PAYMENT_METHOD_TERMINAL_ELEMENT    => [
319
        'currency' => 'RUB',
320
        'image'    => 'design/images/payments/terminal/element.gif',
321
      ],
322
      PAYMENT_METHOD_TERMINAL_KASSIRANET => [
323
        'currency' => 'RUB',
324
        'image'    => 'design/images/payments/terminal/kassira_net.gif',
325
        'button'   => true,
326
      ],
327
    ],
328
329
    PAYMENT_METHOD_OTHER => [
330
      PAYMENT_METHOD_OTHER_EVROSET          => [
331
        'currency' => 'RUB',
332
        'image'    => 'design/images/payments/other/evroset.gif',
333
      ],
334
      PAYMENT_METHOD_OTHER_SVYAZNOY         => [
335
        'currency' => 'RUB',
336
        'image'    => 'design/images/payments/other/svyaznoy.gif',
337
      ],
338
      PAYMENT_METHOD_OTHER_ROBOKASSA_MOBILE => [
339
        'currency' => 'RUB',
340
        'image'    => 'design/images/payments/other/robokassa_mobile.gif',
341
        'name'     => true,
342
      ],
343
    ],
344
345
    PAYMENT_METHOD_GENERIC => [
346
      PAYMENT_METHOD_GENERIC_XSOLLA => [
347
        'currency' => 'UAH',
348
        'image'    => 'design/images/payments/generic/xsolla.png',
349
        'name'     => true,
350
        'button'   => true,
351
      ],
352
353
      PAYMENT_METHOD_GENERIC_ROBOKASSA => [
354
        'currency' => 'RUB',
355
        'image'    => 'design/images/payments/generic/robokassa.jpg',
356
        // 'name' => true,
357
        'button'   => true,
358
      ],
359
    ],
360
  ];
361
362
  /**
363
   * @var Account $account
364
   */
365
  public $account = null;
366
367
  /**
368
   * @var db_mysql $db
369
   */
370
  public $db = null;
371
372
  /**
373
   * @var int
374
   */
375
  public $request_payment_id = 0;
376
  /**
377
   * Идентификатор сервера, на который производится оплата
378
   *
379
   * @var string $request_server_id
380
   */
381
  public $request_server_id = '';
382
  /**
383
   * Идентификатор платящего пользователя
384
   *
385
   * @var int
386
   */
387
  public $request_account_id = 0;
388
  /**
389
   * @var int
390
   */
391
  // public $request_mm_amount = 0;
392
  /**
393
   * @var float
394
   */
395
  // public $request_money_out = 0.0;
396
397
  /**
398
   * Внутренний идентификатор платежа
399
   *
400
   * @var int
401
   */
402
  public $payment_id = 0;
403
  public $payment_status = PAYMENT_STATUS_NONE;
404
  public $payment_provider_id = ACCOUNT_PROVIDER_NONE;
405
  public $payment_account_id = 0;
406
  public $payment_account_name = '';
407
  public $payment_user_id = 0;
408
  public $payment_user_name = '';
409
  public $payment_amount = 0;
410
  public $payment_currency = '';
411
  public $payment_dark_matter_paid = 0;
412
  public $payment_dark_matter_gained = 0;
413
  public $payment_date = SN_TIME_SQL;
414
  public $payment_comment = '';
415
  public $payment_module_name = '';
416
417
  public $payment_external_id = '';
418
  public $payment_external_date = '';
419
  public $payment_external_lots = 0;
420
  public $payment_external_amount = 0;
421
  public $payment_external_currency = '';
422
423
  public $payment_test = 0;
424
425
  public $is_exists = false;
426
  public $is_loaded = false;
427
428
  protected $description_generated = array();
429
430
  protected $debug = false;
431
432
  protected $payment_params = array(
433
//    'server_id' => 'shp_server', // Должен быть server_id
434
//    'account_id' => 'shp_id', // Должен быть user_id
435
//    'payment_id' => 'InvId', // Должен быть внутренний payment_id
436
//    'payment_dark_matter_gained' => 'shp_dm', // TODO - Реально - dark_matter_gained! Что бы учитывались акции!
437
//    'payment_external_money' => 'OutSum', // Количество денег "к оплате" от СН
438
//    'test' => 'shp_z_test', // Тестовый статус аккаунта
439
//    'payment_external_id' => '', // ИД платежа в платёжной системе
440
//    'payment_external_currency' => 'payment_currency', // Валюта платежа в платёжной системе
441
  );
442
443
  protected $result_translations = array(
444
    // Универсальный ответ на неизвестную ошибку
445
    SN_PAYMENT_REQUEST_UNDEFINED_ERROR => SN_PAYMENT_REQUEST_UNDEFINED_ERROR,
446
    // Утвердительный ответ
447
    SN_PAYMENT_REQUEST_OK              => SN_PAYMENT_REQUEST_OK,
448
  );
449
450
  /**
451
   * sn_module_payment constructor.
452
   *
453
   * @param string $filename
454
   *
455
   * @throws Exception
456
   */
457
  public function __construct($filename = __FILE__) {
458
    parent::__construct($filename);
459
460
    if (!empty($this->config['debug'])) {
461
      $this->debug = true;
462
    }
463
  }
464
465
  /**
466
   * @param array $data
467
   */
468
  public function debug($data) {
469
    if (!$this->debug) {
470
      return;
471
    }
472
473
    file_put_contents(SN_ROOT_PHYSICAL . '_' . get_called_class() . '_debug.txt', $data, FILE_APPEND);
474
  }
475
476
  /**
477
   * Компилирует запрос к платёжной системе
478
   *
479
   * @param $request
480
   *
481
   * @throws Exception
482
   */
483
  public function compile_request($request) {
484
    global $config, $lang, $user;
485
486
    if (!(SN::$auth->account instanceof Account)) {
0 ignored issues
show
introduced by
SN::auth->account is always a sub-type of Account.
Loading history...
487
      // TODO - throw new Exception($lang['pay_msg_mm_request_amount_invalid'], SN_PAYMENT_REQUEST_ERROR_UNIT_AMOUNT);
488
    }
489
    $this->account = SN::$auth->account;
490
491
    $this->db = $this->account->db;
492
493
    $this->payment_provider_id = core_auth::$main_provider->provider_id;
494
    $this->payment_account_id = $this->account->account_id;
495
    $this->payment_account_name = $this->account->account_name;
496
    $this->payment_user_id = $user['id'];
497
    $this->payment_user_name = $user['username'];
498
499
    // TODO - минимальное количество ММ к оплате
500
    $this->payment_dark_matter_paid = $request['metamatter'];
501
    $this->payment_dark_matter_gained = self::bonus_calculate($this->payment_dark_matter_paid, true);
502
503
    $this->payment_currency = $config->payment_currency_default;
504
    $this->payment_amount = self::currency_convert($this->payment_dark_matter_paid, 'MM_', $this->payment_currency);
505
506
    if (empty($this->payment_external_currency) && !empty($this->config['currency'])) {
507
      $this->payment_external_currency = $this->config['currency'];
508
    }
509
    if (empty($this->payment_external_currency)) {
510
      throw new Exception($lang['pay_error_internal_no_external_currency_set'], SN_PAYMENT_ERROR_INTERNAL_NO_EXTERNAL_CURRENCY_SET);
511
    }
512
513
    $this->payment_external_amount = self::currency_convert($this->payment_dark_matter_paid, 'MM_', $this->payment_external_currency);
514
    if ($this->payment_external_amount < 0.01) {
515
      throw new Exception($lang['pay_msg_mm_request_amount_invalid'], SN_PAYMENT_REQUEST_ERROR_UNIT_AMOUNT);
516
    }
517
518
    $this->payment_test = !empty($this->config['test']);
519
520
    $this->generate_description();
521
522
    $this->db_insert();
523
    if (!$this->is_exists) {
524
      throw new Exception($lang['pay_msg_request_error_db_payment_create'], SN_PAYMENT_REQUEST_DB_ERROR_PAYMENT_CREATE);
525
    }
526
  }
527
528
  /**
529
   * @param array $options
530
   *
531
   * @return array
532
   * @throws Exception
533
   */
534
  // OK 4.8
535
  protected function payment_request_process($options = array()) {
536
    global $lang, $config;
537
538
    if (!$this->active) {
539
      throw new Exception($lang['pay_msg_module_disabled'], SN_MODULE_DISABLED);
540
    }
541
542
    // Если есть payment_id - загружаем под него данные
543
    if (!empty($this->payment_params['payment_id'])) {
544
      $this->request_payment_id = sys_get_param_id($this->payment_params['payment_id']);
0 ignored issues
show
Documentation Bug introduced by
It seems like sys_get_param_id($this->...t_params['payment_id']) can also be of type string. However, the property $request_payment_id is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
545
      if (!$this->request_payment_id) {
546
        throw new Exception($lang['pay_msg_request_payment_id_invalid'], SN_PAYMENT_REQUEST_INTERNAL_ID_WRONG);
547
      }
548
549
      if (!$this->db_get_by_id($this->request_payment_id)) {
550
        throw new Exception($lang['pay_msg_request_payment_id_invalid'], SN_PAYMENT_REQUEST_INTERNAL_ID_WRONG);
551
      }
552
553
      // Проверяем - был ли этот платеж обработан?
554
      // TODO - Статусы бывают разные. Нужен спецфлаг payment_processed
555
      if ($this->payment_status != PAYMENT_STATUS_NONE && empty($options[self::DO_NOT_REDIRECT])) {
556
        sn_db_transaction_rollback();
557
        sys_redirect(SN_ROOT_VIRTUAL . 'metamatter.php?payment_id=' . $this->payment_id);
558
        die();
0 ignored issues
show
Best Practice introduced by
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...
559
      }
560
    }
561
562
    // Пытаемся получить из запроса ИД аккаунта
563
    $request_account_id = !empty($this->payment_params['account_id']) ? sys_get_param_id($this->payment_params['account_id']) : 0;
564
    // Если в запросе нет ИД аккаунта - пытаемся использовать payment_account_id
565
    if (empty($request_account_id) && !empty($this->payment_account_id)) {
566
      $request_account_id = $this->payment_account_id;
567
    }
568
    // Если теперь у нас нету ИД аккаунта ни в запросе, ни в записи таблицы - можно паниковать
569
    if (empty($request_account_id)) {
570
      // TODO - аккаунт
571
      throw new Exception($lang['pay_msg_request_user_invalid'], $this->retranslate_error(SN_PAYMENT_REQUEST_USER_NOT_FOUND, $options));
572
    }
573
    // Если нет записи в таблице - тогда берем payment_account_id из запроса
574
    if (empty($this->payment_account_id)) {
575
      $this->payment_account_id = $request_account_id;
576
    }
577
    // Если у нас отличаются ИД аккаунта в запросе и ИД аккаунта в записи - тоже можно паниковать
578
    if ($this->payment_account_id != $request_account_id) {
579
      // TODO - Поменять сообщение об ошибке
580
      throw new Exception($lang['pay_msg_request_user_invalid'], $this->retranslate_error(SN_PAYMENT_REQUEST_USER_NOT_FOUND, $options));
581
    }
582
    // Проверяем существование аккаунта с данным ИД
583
    if (!$this->account->db_get_by_id($this->payment_account_id)) {
584
      throw new Exception($lang['pay_msg_request_user_invalid'] . ' ID ' . $this->payment_account_id, $this->retranslate_error(SN_PAYMENT_REQUEST_USER_NOT_FOUND, $options));
585
    }
586
587
    // TODO Проверка на сервер_ид - как бы и не нужна, наверное?
588
    if (!empty($this->payment_params['server_id'])) {
589
      $this->request_server_id = sys_get_param_str($this->payment_params['server_id']);
590
      if (SN_ROOT_VIRTUAL != $this->request_server_id) {
591
        throw new Exception($lang['pay_msg_request_server_wrong'] . " {$this->request_server_id} вместо " . SN_ROOT_VIRTUAL, SN_PAYMENT_REQUEST_SERVER_WRONG);
592
      }
593
    }
594
595
    // Сверка количества оплаченной ММ с учётом бонусов
596
    if (!empty($this->payment_params['payment_dark_matter_gained'])) {
597
      $request_mm_amount = sys_get_param_id($this->payment_params['payment_dark_matter_gained']);
598
      if ($request_mm_amount != $this->payment_dark_matter_gained && $this->is_loaded) {
599
        throw new Exception($lang['pay_msg_mm_request_amount_invalid'] . " пришло {$request_mm_amount} ММ вместо {$this->payment_dark_matter_gained} ММ", SN_PAYMENT_REQUEST_MM_AMOUNT_INVALID);
600
      }
601
      empty($this->payment_dark_matter_gained) ? $this->payment_dark_matter_gained = $request_mm_amount : false;
602
    }
603
    if (empty($this->payment_dark_matter_paid)) {
604
      // TODO - обратный расчёт из gained
605
    }
606
607
    // Проверка наличия внешнего ИД платежа
608
    if (!empty($this->payment_params['payment_external_id'])) {
609
      $request_payment_external_id = sys_get_param_id($this->payment_params['payment_external_id']);
610
      if (empty($request_payment_external_id)) {
611
        throw new exception($lang['pay_msg_request_payment_id_invalid'], SN_PAYMENT_REQUEST_EXTERNAL_ID_WRONG);
612
      } elseif (!empty($this->payment_external_id) && $this->payment_external_id != $request_payment_external_id) {
613
        // TODO - Может быть поменять сообщение
614
        throw new exception($lang['pay_msg_request_payment_id_invalid'], SN_PAYMENT_REQUEST_EXTERNAL_ID_WRONG);
615
      }
616
      $this->payment_external_id = $request_payment_external_id;
617
    }
618
    // Сверка суммы, запрошенной СН к оплате
619
    if (!empty($this->payment_params['payment_external_money'])) {
620
      $request_money_out = sys_get_param_float($this->payment_params['payment_external_money']);
621
      if ($request_money_out != $this->payment_external_amount && $this->is_loaded) {
622
        throw new Exception($lang['pay_msg_request_payment_amount_invalid'] . " пришло {$request_money_out} денег вместо {$this->payment_external_amount} денег", SN_PAYMENT_REQUEST_CURRENCY_AMOUNT_INVALID);
623
      }
624
      empty($this->payment_external_amount) ? $this->payment_external_amount = $request_money_out : false;
625
    }
626
    // Заполняем поле валюты платёжной системы
627
    if (!empty($this->payment_params['payment_external_currency'])) {
628
      $this->payment_external_currency = sys_get_param_str($this->payment_params['payment_external_currency']);
629
      if (empty($this->payment_external_currency)) {
630
        // TODO - поменять сообщение
631
        throw new Exception($lang['pay_msg_request_payment_amount_invalid'] . " {$this->payment_external_currency}", SN_PAYMENT_REQUEST_CURRENCY_AMOUNT_INVALID);
632
      }
633
    }
634
    if (empty($this->payment_external_currency)) {
635
      $this->payment_external_currency = $this->config['currency'];
636
    }
637
638
    // Заполнение внутренней суммы и валюты из внешних данных
639
    if (empty($this->payment_currency)) {
640
      $this->payment_currency = $config->payment_currency_default;
641
    }
642
    if (empty($this->payment_amount) && !empty($this->payment_external_currency)) {
643
      $this->payment_amount = self::currency_convert($this->payment_external_amount, $this->payment_external_currency, $this->payment_currency);
644
    }
645
646
    // TODO - Тестовый режим
647
    if (!empty($this->payment_params['test'])) {
648
      $this->payment_test = $this->config['test'] || sys_get_param_int($this->payment_params['test']);
649
    }
650
651
    $this->generate_description();
652
653
//    // TODO - REMOVE
654
//    return array(
655
//      'payer' => $this->account,
656
//    );
657
  }
658
659
  /**
660
   * Точка входа для коллбэка системы платежей - вызывается из <class_name>_response.php
661
   *
662
   * @return array
663
   */
664
  // OK 4.8
665
  // TODO - Здесь должно происходить разделение на resultURL, successURL, failURL
666
  public function payment_request_response() {
667
    global $debug;
668
669
    $this->db = core_auth::$main_provider->db;
670
    $this->account = new Account($this->db);
671
672
    // TODO - REPLACE WITH INNATE CALL!
673
    sn_db_transaction_start();
674
    try {
675
      $response = $this->payment_request_process();
676
    } catch (Exception $e) {
677
      $response['result'] = $e->getCode();
678
      $response['message'] = $e->getMessage();
679
680
      $this->debug([
681
        "\n",
682
        "Kinda Error!\n",
683
        '$response => ', var_export($response, true),
684
        "\n",
685
      ]);
686
    }
687
688
    if ($response['result'] == SN_PAYMENT_REQUEST_OK) {
689
      sn_db_transaction_commit();
690
      $debug->warning('Результат операции: код ' . $response['result'] . ' сообщение "' . $response['message'] . '"', 'Успешный платёж', LOG_INFO_PAYMENT);
691
    } else {
692
      sn_db_transaction_rollback();
693
      $debug->warning('Результат операции: код ' . $response['result'] . ' сообщение "' . $response['message'] . '"', 'Ошибка платежа', LOG_INFO_PAYMENT, true);
694
    }
695
696
    // Переводим код результата из СН в код платежной системы
697
    if (is_array($this->result_translations) && !empty($this->result_translations)) {
698
      $response['result'] = isset($this->result_translations[$response['result']]) ? $this->result_translations[$response['result']] : $this->result_translations[SN_PAYMENT_REQUEST_UNDEFINED_ERROR];
699
    }
700
701
    return $response;
702
  }
703
704
705
  // Function converts money values between currencies
706
707
  /**
708
   * Внутриигровая конвертация валют
709
   *
710
   * @param        $value
711
   * @param string $currency_from
712
   * @param string $currency_to
713
   * @param int    $round
714
   *
715
   * @return float|int
716
   */
717
  public static function currency_convert($value, $currency_from = '', $currency_to = '', $round = 2) {
718
//    global $config;
719
720
    $currency_from = strtolower($currency_from);
721
    $currency_to = strtolower($currency_to);
722
723
    if ($currency_from != $currency_to) {
724
//      $config_currency_from_name = 'payment_currency_exchange_' . $currency_from;
725
//      $config_currency_to_name = 'payment_currency_exchange_' . $currency_to;
726
727
//      $exchange_from = floatval($currency_from == 'mm_' ? get_mm_cost() : $config->$config_currency_from_name);
728
//      $exchange_to = floatval($currency_to == 'mm_' ? get_mm_cost() : $config->$config_currency_to_name);
729
730
      $exchange_from = get_exchange_rate($currency_from);
731
      $exchange_to = get_exchange_rate($currency_to);
732
733
      $value = $exchange_from ? $value / $exchange_from * $exchange_to * pow(10, $round) : 0;
734
      $value = ceil($value) / pow(10, $round);
735
    }
736
737
    return $value;
738
  }
739
740
  // Function calculates bonused DM amount for bulk purchase and ($direct = false) vice versa
741
742
  /**
743
   * Рассчёт бонуса ММ
744
   *
745
   * @param            $dark_matter
746
   * @param bool|true  $direct
747
   * @param bool|false $return_bonus
748
   *
749
   * @return float|int
750
   */
751
  public static function bonus_calculate($dark_matter, $direct = true, $return_bonus = false) {
752
    $bonus = 0;
753
    $dark_matter_new = $dark_matter;
754
    if (!empty(self::$bonus_table) && $dark_matter >= self::$bonus_table[0]) {
755
      if ($direct) {
756
        foreach (self::$bonus_table as $dm_for_bonus => $multiplier) {
757
          if ($dm_for_bonus <= $dark_matter) {
758
            $dark_matter_new = $dark_matter * (1 + $multiplier);
759
            $bonus = $multiplier;
760
          } else {
761
            break;
762
          }
763
        }
764
      } else {
765
        foreach (self::$bonus_table as $dm_for_bonus => $multiplier) {
766
          $temp = $dm_for_bonus * (1 + $multiplier);
767
          if ($dark_matter >= $temp) {
768
            $dark_matter_new = round($dark_matter / (1 + $multiplier));
769
            $bonus = $multiplier;
770
          } else {
771
            break;
772
          }
773
        }
774
      }
775
    }
776
777
    return $return_bonus ? $bonus : $dark_matter_new;
778
  }
779
780
  // Дополнительная ре-трансляция адреса, если в каком-то случае платежная система ожидает нелогичный ответ
781
  // Пример: иксолла при неправильно заданном пользователе в ордере ожидает НЕПРАВИЛЬНЫЙ_ОРДЕР, а не НЕПРАВИЛЬНЫЙ_ПОЛЬЗОВАТЕЛЬ
782
  function retranslate_error($error_code, $options = array()) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
783
    return isset($options['retranslate_error'][$error_code]) ? $options['retranslate_error'][$error_code] : $error_code;
784
  }
785
786
787
  function db_insert() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
788
    global $config;
789
790
    $this->payment_test = !empty($this->config['test']) || $this->payment_test;
791
792
    $payment = array(
793
      'payment_module_name' => $this->manifest['name'],
794
795
      'payment_status' => $this->payment_status,
796
      // 'payment_date' => $this->payment_date, // Не нужно
797
798
      'payment_provider_id'  => $this->payment_provider_id,
799
      'payment_account_id'   => $this->payment_account_id,
800
      'payment_account_name' => $this->payment_account_name,
801
      'payment_user_id'      => $this->payment_user_id,
802
      'payment_user_name'    => $this->payment_user_name,
803
804
      'payment_dark_matter_paid'   => $this->payment_dark_matter_paid,
805
      'payment_dark_matter_gained' => $this->payment_dark_matter_gained,
806
807
      'payment_amount'   => $this->payment_amount,
808
      'payment_currency' => $this->payment_currency,
809
810
      'payment_external_id'       => $this->payment_external_id, // TODO
811
      'payment_external_amount'   => $this->payment_external_amount,
812
      'payment_external_currency' => $this->payment_external_currency,
813
      'payment_external_date'     => $this->payment_external_date, // TODO
814
815
      'payment_test' => $this->payment_test ? 1 : 0, // Boolean -> int
816
817
      'payment_comment' => $this->description_generated[PAYMENT_DESCRIPTION_MAX],
818
819
      'payment_external_lots' => $this->payment_dark_matter_paid / get_mm_cost(),
820
    );
821
822
    $replace = false;
823
    if ($this->payment_id) {
824
      $payment['payment_id'] = $this->payment_id;
825
      $replace = true;
826
    }
827
828
    $query = array();
829
    foreach ($payment as $key => $value) {
830
      $value = is_string($value) ? '"' . db_escape($value) . '"' : $value;
831
      $query[] = "`{$key}` = {$value}";
832
    }
833
834
    $this->db->doquery(($replace ? 'REPLACE' : 'INSERT') . ' INTO `{{payment}}` SET ' . implode(',', $query) . ';');
835
836
    return $this->db_get_by_id($this->db->db_insert_id());
837
  }
838
839
840
  function payment_adjust_mm_new() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
841
    if (!$this->payment_test) {
842
      // Not a test payment. Adding DM to account
843
      $this->account = new Account($this->db);
844
      $this->account->db_get_by_id($this->payment_account_id);
845
      $result = $this->account->metamatter_change(RPG_PURCHASE, $this->payment_dark_matter_gained, $this->payment_comment);
846
      if (!$result) {
847
        throw new Exception('Ошибка начисления ММ', SN_METAMATTER_ERROR_ADJUST);
848
      }
849
    }
850
  }
851
852
  function payment_cancel(&$payment) {
0 ignored issues
show
Unused Code introduced by
The parameter $payment 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

852
  function payment_cancel(/** @scrutinizer ignore-unused */ &$payment) {

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...
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
853
    die('{НЕ РАБОТАЕТ! СООБЩИТЕ АДМИНИСТРАЦИИ!}');
0 ignored issues
show
Best Practice introduced by
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...
854
    global $lang;
0 ignored issues
show
Unused Code introduced by
GlobalNode is not reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
855
856
    if (!isset($payment['payment_status'])) {
857
      throw new exception($lang['pay_msg_request_payment_not_found'], SN_PAYMENT_REQUEST_ORDER_NOT_FOUND);
858
    }
859
860
    if ($payment['payment_status'] == PAYMENT_STATUS_COMPLETE) {
861
      $safe_comment = db_escape($payment['payment_comment'] = $lang['pay_msg_request_payment_cancelled'] . ' ' . $payment['payment_comment']);
862
863
      if (!$payment['payment_test']) {
864
        $result = $this->account->metamatter_change(RPG_PURCHASE_CANCEL, -$payment['payment_dark_matter_gained'], $payment['payment_comment']);
865
        if (!$result) {
866
          throw new exception('Ошибка начисления ММ', SN_METAMATTER_ERROR_ADJUST);
867
        }
868
      }
869
      $payment['payment_status'] = PAYMENT_STATUS_CANCELED;
870
      doquery("UPDATE {{payment}} SET payment_status = {$payment['payment_status']}, payment_comment = '{$safe_comment}' WHERE payment_id = {$payment['payment_id']};");
0 ignored issues
show
Deprecated Code introduced by
The function doquery() has been deprecated. ( Ignorable by Annotation )

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

870
      /** @scrutinizer ignore-deprecated */ doquery("UPDATE {{payment}} SET payment_status = {$payment['payment_status']}, payment_comment = '{$safe_comment}' WHERE payment_id = {$payment['payment_id']};");
Loading history...
871
      throw new exception($lang['pay_msg_request_payment_cancel_complete'], SN_PAYMENT_REQUEST_OK);
872
    } elseif ($payment['payment_status'] == PAYMENT_STATUS_CANCELED) {
873
      throw new exception($lang['pay_msg_request_payment_cancelled_already'], SN_PAYMENT_REQUEST_OK);
874
    } elseif ($payment['payment_status'] == PAYMENT_STATUS_NONE) {
875
      throw new exception($lang['pay_msg_request_payment_cancel_not_complete'], SN_PAYMENT_REQUEST_PAYMENT_NOT_COMPLETE);
876
    }
877
  }
878
879
880
  protected function db_get_by_id($payment_id_unsafe) {
881
    $payment_id_internal_safe = $this->db->db_escape($payment_id_unsafe);
882
    $payment = $this->db->doQueryAndFetch(
883
      "SELECT * 
884
      FROM {{payment}} 
885
      WHERE 
886
        `payment_module_name` = '{$this->manifest['name']}' 
887
        AND `payment_id` = '{$payment_id_internal_safe}' 
888
        LIMIT 1 FOR UPDATE;"
889
    );
890
891
    return $this->db_assign_payment($payment);
892
  }
893
894
  protected function db_complete_payment() {
895
    // TODO - поле payment_processed
896
    if ($this->payment_status == PAYMENT_STATUS_NONE) {
897
      if (!defined('PAYMENT_EXPIRE_TIME') || PAYMENT_EXPIRE_TIME == 0 || empty($this->payment_date) || strtotime($this->payment_date) + PAYMENT_EXPIRE_TIME <= SN_TIME_NOW) {
0 ignored issues
show
introduced by
The condition PAYMENT_EXPIRE_TIME == 0 is always true.
Loading history...
898
        $this->payment_adjust_mm_new();
899
        $this->payment_status = PAYMENT_STATUS_COMPLETE;
900
      } else {
901
        $this->payment_status = PAYMENT_STATUS_EXPIRED;
902
      }
903
904
      $this->db_insert();
905
    }
906
  }
907
908
  protected function payment_reset() {
909
    $this->payment_id = 0;
910
    $this->payment_status = PAYMENT_STATUS_NONE;
911
912
    $this->payment_provider_id = ACCOUNT_PROVIDER_NONE;
913
    $this->payment_account_id = 0;
914
    $this->payment_account_name = '';
915
    $this->payment_user_id = 0;
916
    $this->payment_user_name = '';
917
918
    $this->payment_amount = 0;
919
    $this->payment_currency = '';
920
921
    $this->payment_dark_matter_paid = 0;
922
    $this->payment_dark_matter_gained = 0;
923
    $this->payment_date = SN_TIME_SQL;
924
    $this->payment_comment = '';
925
    $this->payment_module_name = '';
926
927
    $this->payment_external_id = '';
928
    $this->payment_external_date = '';
929
    $this->payment_external_lots = 0;
930
    $this->payment_external_amount = 0;
931
    $this->payment_external_currency = '';
932
933
    $this->payment_test = 0;
934
935
    $this->is_exists = false;
936
    $this->is_loaded = false;
937
938
    $this->description_generated = array();
939
  }
940
941
  protected function db_assign_payment($payment = null) {
942
    $this->payment_reset();
943
944
    if (is_array($payment) && isset($payment['payment_id'])) {
945
      $this->payment_id = $payment['payment_id'];
946
      $this->payment_status = $payment['payment_status'];
947
      $this->payment_date = $payment['payment_date'];
948
949
      $this->payment_provider_id = $payment['payment_provider_id'];
950
      $this->payment_account_id = $payment['payment_account_id'];
951
      $this->payment_account_name = $payment['payment_account_name'];
952
      $this->payment_user_id = $payment['payment_user_id'];
953
      $this->payment_user_name = $payment['payment_user_name'];
954
955
      $this->payment_amount = $payment['payment_amount'];
956
      $this->payment_currency = $payment['payment_currency'];
957
958
      $this->payment_dark_matter_paid = $payment['payment_dark_matter_paid'];
959
      $this->payment_dark_matter_gained = $payment['payment_dark_matter_gained'];
960
961
      $this->payment_comment = $payment['payment_comment'];
962
      $this->payment_module_name = $payment['payment_module_name'];
963
964
      $this->payment_external_id = $payment['payment_external_id'];
965
      $this->payment_external_date = $payment['payment_external_date'];
966
      $this->payment_external_lots = $payment['payment_external_lots'];
967
      $this->payment_external_amount = $payment['payment_external_amount'];
968
      $this->payment_external_currency = $payment['payment_external_currency'];
969
970
      $this->payment_test = $payment['payment_test'];
971
972
      $this->is_exists = true;
973
      $this->is_loaded = true;
974
975
      $this->generate_description();
976
977
      return true;
978
    } else {
979
      return false;
980
    }
981
  }
982
983
  protected function generate_description() {
984
    // TODO - системная локализация
985
    $this->description_generated = array(
986
      PAYMENT_DESCRIPTION_100 => substr("{$this->payment_dark_matter_gained} ММ аккаунт [{$this->account->account_name}] ID {$this->account->account_id} на " . SN_ROOT_VIRTUAL, 0, 100),
987
      PAYMENT_DESCRIPTION_250 => substr("Оплата {$this->payment_dark_matter_gained} ММ для аккаунта [{$this->payment_user_name}] ID {$this->payment_user_id} на сервере " . SN_ROOT_VIRTUAL, 0, 250),
988
      PAYMENT_DESCRIPTION_MAX => ($this->payment_test ? "ТЕСТОВЫЙ ПЛАТЕЖ! " : '') .
989
        "Платеж от аккаунта '{$this->payment_account_name}' ID {$this->payment_account_id} игрока '{$this->payment_user_name}' ID {$this->payment_user_id} на сервере " . SN_ROOT_VIRTUAL .
990
        " сумма {$this->payment_amount} {$this->payment_currency} за {$this->payment_dark_matter_paid} ММ (начислено {$this->payment_dark_matter_gained} ММ)" .
991
        " через '{$this->manifest['name']}' сумма {$this->payment_external_amount} {$this->payment_external_currency}",
992
    );
993
  }
994
995
}
996