Issues (32)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

sdk/AllPay.Payment.Integration.php (27 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * 付款方式。
5
 */
6
abstract class PaymentMethod
7
{
8
    /**
9
     * 不指定付款方式。
10
     */
11
    const ALL = 'ALL';
12
13
    /**
14
     * 信用卡付費。
15
     */
16
    const Credit = 'Credit';
17
18
    /**
19
     * 網路 ATM。
20
     */
21
    const WebATM = 'WebATM';
22
23
    /**
24
     * 自動櫃員機。
25
     */
26
    const ATM = 'ATM';
27
28
    /**
29
     * 超商代碼。
30
     */
31
    const CVS = 'CVS';
32
33
    /**
34
     * 財付通。
35
     */
36
    const Tenpay = 'Tenpay';
37
38
    /**
39
     * 儲值消費。
40
     */
41
    const TopUpUsed = 'TopUpUsed';
42
}
43
44
/**
45
 * 付款方式子項目。
46
 */
47
abstract class PaymentMethodItem
48
{
49
    /**
50
     * 不指定。
51
     */
52
    const None = '';
53
    // WebATM 類(001~100)
54
    /**
55
     * 台新銀行。
56
     */
57
    const WebATM_TAISHIN = 'TAISHIN';
58
59
    /**
60
     * 玉山銀行。
61
     */
62
    const WebATM_ESUN = 'ESUN';
63
64
    /**
65
     * 華南銀行。
66
     */
67
    const WebATM_HUANAN = 'HUANAN';
68
69
    /**
70
     * 台灣銀行。
71
     */
72
    const WebATM_BOT = 'BOT';
73
74
    /**
75
     * 台北富邦。
76
     */
77
    const WebATM_FUBON = 'FUBON';
78
79
    /**
80
     * 中國信託。
81
     */
82
    const WebATM_CHINATRUST = 'CHINATRUST';
83
84
    /**
85
     * 第一銀行。
86
     */
87
    const WebATM_FIRST = 'FIRST';
88
89
    /**
90
     * 國泰世華。
91
     */
92
    const WebATM_CATHAY = 'CATHAY';
93
94
    /**
95
     * 兆豐銀行。
96
     */
97
    const WebATM_MEGA = 'MEGA';
98
99
    /**
100
     * 元大銀行。
101
     */
102
    const WebATM_YUANTA = 'YUANTA';
103
104
    /**
105
     * 土地銀行。
106
     */
107
    const WebATM_LAND = 'LAND';
108
    // ATM 類(101~200)
109
    /**
110
     * 台新銀行。
111
     */
112
    const ATM_TAISHIN = 'TAISHIN';
113
114
    /**
115
     * 玉山銀行。
116
     */
117
    const ATM_ESUN = 'ESUN';
118
119
    /**
120
     * 華南銀行。
121
     */
122
    const ATM_HUANAN = 'HUANAN';
123
124
    /**
125
     * 台灣銀行。
126
     */
127
    const ATM_BOT = 'BOT';
128
129
    /**
130
     * 台北富邦。
131
     */
132
    const ATM_FUBON = 'FUBON';
133
134
    /**
135
     * 中國信託。
136
     */
137
    const ATM_CHINATRUST = 'CHINATRUST';
138
139
    /**
140
     * 土地銀行。
141
     */
142
    const ATM_LAND = 'LAND';
143
144
    /**
145
     * 國泰世華銀行。
146
     */
147
    const ATM_CATHAY = 'CATHAY';
148
149
    /**
150
     * 大眾銀行。
151
     */
152
    const ATM_Tachong = 'Tachong';
153
154
    /**
155
     * 永豐銀行。
156
     */
157
    const ATM_Sinopac = 'Sinopac';
158
159
    /**
160
     * 彰化銀行。
161
     */
162
    const ATM_CHB = 'CHB';
163
164
    /**
165
     * 第一銀行。
166
     */
167
    const ATM_FIRST = 'FIRST';
168
169
    // 超商類(201~300)
170
    /**
171
     * 超商代碼繳款。
172
     */
173
    const CVS = 'CVS';
174
175
    /**
176
     * OK超商代碼繳款。
177
     */
178
    const CVS_OK = 'OK';
179
180
    /**
181
     * 全家超商代碼繳款。
182
     */
183
    const CVS_FAMILY = 'FAMILY';
184
185
    /**
186
     * 萊爾富超商代碼繳款。
187
     */
188
    const CVS_HILIFE = 'HILIFE';
189
190
    /**
191
     * 7-11 ibon代碼繳款。
192
     */
193
    const CVS_IBON = 'IBON';
194
    // 其他第三方支付類(301~400)
195
196
    /**
197
     * 財付通。
198
     */
199
    const Tenpay = 'Tenpay';
200
    // 儲值/餘額消費類(401~500)
201
    /**
202
     * 儲值/餘額消費(歐付寶).
203
     */
204
    const TopUpUsed_AllPay = 'AllPay';
205
206
    /**
207
     * 儲值/餘額消費(玉山).
208
     */
209
    const TopUpUsed_ESUN = 'ESUN';
210
    // 其他類(901~999)
211
212
    /**
213
     * 信用卡(MasterCard/JCB/VISA)。
214
     */
215
    const Credit = 'Credit';
216
217
    /**
218
     * 貨到付款。
219
     */
220
    const COD = 'COD';
221
}
222
223
/**
224
 * 額外付款資訊。
225
 */
226
abstract class ExtraPaymentInfo
227
{
228
    /**
229
     * 需要額外付款資訊。
230
     */
231
    const Yes = 'Y';
232
233
    /**
234
     * 不需要額外付款資訊。
235
     */
236
    const No = 'N';
237
}
238
239
/**
240
 * 額外付款資訊。
241
 */
242
abstract class DeviceType
243
{
244
    /**
245
     * 桌機版付費頁面。
246
     */
247
    const PC = 'P';
248
249
    /**
250
     * 行動裝置版付費頁面。
251
     */
252
    const Mobile = 'M';
253
}
254
255
/**
256
 * 信用卡訂單處理動作資訊。
257
 */
258
abstract class ActionType
259
{
260
    /**
261
     * 關帳.
262
     */
263
    const C = 'C';
264
265
    /**
266
     * 退刷.
267
     */
268
    const R = 'R';
269
270
    /**
271
     * 取消.
272
     */
273
    const E = 'E';
274
275
    /**
276
     * 放棄.
277
     */
278
    const N = 'N';
279
}
280
281
/**
282
 * 定期定額的週期種類。
283
 */
284
abstract class PeriodType
285
{
286
    /**
287
     * 無
288
     */
289
    const None = '';
290
291
    /**
292
     * 年.
293
     */
294
    const Year = 'Y';
295
296
    /**
297
     * 月.
298
     */
299
    const Month = 'M';
300
301
    /**
302
     * 日.
303
     */
304
    const Day = 'D';
305
}
306
307
/**
308
 * 電子發票開立註記。
309
 */
310
abstract class InvoiceState
311
{
312
    /**
313
     * 需要開立電子發票。
314
     */
315
    const Yes = 'Y';
316
317
    /**
318
     * 不需要開立電子發票。
319
     */
320
    const No = '';
321
}
322
323
/**
324
 * 電子發票載具類別.
325
 */
326
abstract class CarruerType
327
{
328
    // 無載具
329
    const None = '';
330
331
    // 會員載具
332
    const Member = '1';
333
334
    // 買受人自然人憑證
335
    const Citizen = '2';
336
337
    // 買受人手機條碼
338
    const Cellphone = '3';
339
}
340
341
/**
342
 * 電子發票列印註記.
343
 */
344
abstract class PrintMark
345
{
346
    // 不列印
347
    const No = '0';
348
349
    // 列印
350
    const Yes = '1';
351
}
352
353
/**
354
 * 電子發票捐贈註記.
355
 */
356
abstract class Donation
357
{
358
    // 捐贈
359
    const Yes = '1';
360
361
    // 不捐贈
362
    const No = '2';
363
}
364
365
/**
366
 * 通關方式.
367
 */
368
abstract class ClearanceMark
369
{
370
    // 經海關出口
371
    const Yes = '1';
372
373
    // 非經海關出口
374
    const No = '2';
375
}
376
377
/**
378
 * 課稅類別.
379
 */
380
abstract class TaxType
381
{
382
    // 應稅
383
    const Dutiable = '1';
384
385
    // 零稅率
386
    const Zero = '2';
387
388
    // 免稅
389
    const Free = '3';
390
391
    // 應稅與免稅混合(限收銀機發票無法分辦時使用,且需通過申請核可)
392
    const Mix = '9';
393
}
394
395
/**
396
 * 字軌類別.
397
 */
398
abstract class InvType
399
{
400
    // 一般稅額
401
    const General = '07';
402
403
    // 特種稅額
404
    const Special = '08';
405
}
406
407
abstract class EncryptType
408
{
409
    // MD5(預設)
410
    const ENC_MD5 = 0;
411
412
    // SHA256
413
    const ENC_SHA256 = 1;
414
}
415
416
abstract class UseRedeem
417
{
418
    //使用紅利/購物金
419
    const Yes = 'Y';
420
421
    //不使用紅利/購物金
422
    const No = 'N';
423
}
424
425
class AllInOne
426
{
427
    public $ServiceURL = 'ServiceURL';
428
    public $ServiceMethod = 'ServiceMethod';
429
    public $HashKey = 'HashKey';
430
    public $HashIV = 'HashIV';
431
    public $MerchantID = 'MerchantID';
432
    public $PaymentType = 'PaymentType';
433
    public $Send = 'Send';
434
    public $SendExtend = 'SendExtend';
435
    public $Query = 'Query';
436
    public $Action = 'Action';
437
    public $ChargeBack = 'ChargeBack';
438
    public $EncryptType = EncryptType::ENC_MD5;
439
440
    public function __construct()
441
    {
442
        $this->PaymentType = 'aio';
443
        $this->Send = [
0 ignored issues
show
Documentation Bug introduced by
It seems like array('ReturnURL' => '',... => 0, 'StoreID' => '') of type array<string,string|arra...r","StoreID":"string"}> is incompatible with the declared type string of property $Send.

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...
444
            'ReturnURL'         => '',
445
            'ClientBackURL'     => '',
446
            'OrderResultURL'    => '',
447
            'MerchantTradeNo'   => '',
448
            'MerchantTradeDate' => '',
449
            'PaymentType'       => 'aio',
450
            'TotalAmount'       => '',
451
            'TradeDesc'         => '',
452
            'ChoosePayment'     => PaymentMethod::ALL,
453
            'Remark'            => '',
454
            'ChooseSubPayment'  => PaymentMethodItem::None,
455
            'NeedExtraPaidInfo' => ExtraPaymentInfo::No,
456
            'DeviceSource'      => '',
457
            'IgnorePayment'     => '',
458
            'PlatformID'        => '',
459
            'InvoiceMark'       => InvoiceState::No,
460
            'Items'             => [],
461
            'UseRedeem'         => UseRedeem::No,
462
            'HoldTradeAMT'      => 0,
463
            'StoreID'           => '',
464
        ];
465
466
        $this->SendExtend = [];
467
468
        $this->Query = [
469
            'MerchantTradeNo' => '',
470
            'TimeStamp' => '',
471
        ];
472
        $this->Action = [
0 ignored issues
show
Documentation Bug introduced by
It seems like array('MerchantTradeNo' ...:C, 'TotalAmount' => 0) of type array<string,string|inte...otalAmount":"integer"}> is incompatible with the declared type string of property $Action.

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...
473
            'MerchantTradeNo' => '',
474
            'TradeNo' => '',
475
            'Action' => ActionType::C,
476
            'TotalAmount' => 0,
477
        ];
478
        $this->ChargeBack = [
0 ignored issues
show
Documentation Bug introduced by
It seems like array('MerchantTradeNo' ...' => 0, 'Remark' => '') of type array<string,string|inte...er","Remark":"string"}> is incompatible with the declared type string of property $ChargeBack.

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...
479
            'MerchantTradeNo' => '',
480
            'TradeNo' => '',
481
            'ChargeBackTotalAmount' => 0,
482
            'Remark' => '',
483
        ];
484
        $this->Capture = [
0 ignored issues
show
The property Capture does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
485
            'MerchantTradeNo' => '',
486
            'CaptureAMT' => 0,
487
            'UserRefundAMT' => 0,
488
            'PlatformID' => '',
489
        ];
490
491
        $this->TradeNo = [
0 ignored issues
show
The property TradeNo does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
492
            'DateType' => '',
493
            'BeginDate' => '',
494
            'EndDate' => '',
495
            'MediaFormated' => '',
496
        ];
497
498
        $this->Trade = [
0 ignored issues
show
The property Trade does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
499
            'CreditRefundId' => '',
500
            'CreditAmount' => '',
501
            'CreditCheckCode' => '',
502
        ];
503
504
        $this->Funding = [
0 ignored issues
show
The property Funding does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
505
            'PayDateType' => '',
506
            'StartDate' => '',
507
            'EndDate' => '',
508
        ];
509
    }
510
511
    //產生訂單
512
    public function CheckOut($target = '_self')
513
    {
514
        $arParameters = array_merge(['MerchantID' => $this->MerchantID, 'EncryptType' => $this->EncryptType], $this->Send);
515
        Send::CheckOut($target, $arParameters, $this->SendExtend, $this->HashKey, $this->HashIV, $this->ServiceURL);
516
    }
517
518
    //產生訂單html code
519
    public function CheckOutString($paymentButton = null, $target = '_self')
0 ignored issues
show
The parameter $target is not used and could be removed.

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

Loading history...
520
    {
521
        $arParameters = array_merge(['MerchantID' => $this->MerchantID, 'EncryptType' => $this->EncryptType], $this->Send);
522
523
        return Send::CheckOutString($paymentButton, $target = '_self', $arParameters, $this->SendExtend, $this->HashKey, $this->HashIV, $this->ServiceURL);
524
    }
525
526
    //取得付款結果通知的方法
527
    public function CheckOutFeedback()
528
    {
529
        return $arFeedback = CheckOutFeedback::CheckOut(array_merge($_POST, ['EncryptType' => $this->EncryptType]), $this->HashKey, $this->HashIV, 0);
0 ignored issues
show
The call to CheckOutFeedback::CheckOut() has too many arguments starting with 0.

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.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
$arFeedback is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
530
    }
531
532
    //訂單查詢作業
533
    public function QueryTradeInfo()
534
    {
535
        return $arFeedback = QueryTradeInfo::CheckOut(array_merge($this->Query, ['MerchantID' => $this->MerchantID, 'EncryptType' => $this->EncryptType]), $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
$arFeedback is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
536
    }
537
538
    //信用卡定期定額訂單查詢的方法
539
    public function QueryPeriodCreditCardTradeInfo()
540
    {
541
        return $arFeedback = QueryPeriodCreditCardTradeInfo::CheckOut(array_merge($this->Query, ['MerchantID' => $this->MerchantID, 'EncryptType' => $this->EncryptType]), $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
$arFeedback is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
542
    }
543
544
    //信用卡關帳/退刷/取消/放棄的方法
545
    public function DoAction()
546
    {
547
        return $arFeedback = DoAction::CheckOut(array_merge($this->Action, ['MerchantID' => $this->MerchantID, 'EncryptType' => $this->EncryptType]), $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
$arFeedback is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
548
    }
549
550
    //廠商通知退款
551
    public function AioChargeback()
552
    {
553
        return $arFeedback = AioChargeback::CheckOut(array_merge($this->ChargeBack, ['MerchantID' => $this->MerchantID, 'EncryptType' => $this->EncryptType]), $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
$arFeedback is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
554
    }
555
556
    //會員申請撥款/退款
557
    public function AioCapture()
558
    {
559
        return $arFeedback = AioCapture::Capture(array_merge($this->Capture, ['MerchantID' => $this->MerchantID, 'EncryptType' => $this->EncryptType]), $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
$arFeedback is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
560
    }
561
562
    //下載會員對帳媒體檔
563
    public function TradeNoAio($target = '_self')
564
    {
565
        $arParameters = array_merge(['MerchantID' => $this->MerchantID, 'EncryptType' => $this->EncryptType], $this->TradeNo);
566
        TradeNoAio::CheckOut($target, $arParameters, $this->HashKey, $this->HashIV, $this->ServiceURL);
567
    }
568
569
    //查詢信用卡單筆明細紀錄
570
    public function QueryTrade()
571
    {
572
        return $arFeedback = QueryTrade::CheckOut(array_merge($this->Trade, ['MerchantID' => $this->MerchantID, 'EncryptType' => $this->EncryptType]), $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
$arFeedback is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
573
    }
574
575
    //下載信用卡撥款對帳資料檔
576
    public function FundingReconDetail($target = '_self')
577
    {
578
        $arParameters = array_merge(['MerchantID' => $this->MerchantID, 'EncryptType' => $this->EncryptType], $this->Funding);
579
        FundingReconDetail::CheckOut($target, $arParameters, $this->HashKey, $this->HashIV, $this->ServiceURL);
580
    }
581
}
582
583
/**
584
 * 抽象類.
585
 */
586
abstract class Aio
587
{
588
    protected static function ServerPost($parameters, $ServiceURL)
589
    {
590
        $ch = curl_init();
591
592
        if (false === $ch) {
593
            throw new Exception('curl failed to initialize');
594
        }
595
596
        curl_setopt($ch, CURLOPT_URL, $ServiceURL);
597
        curl_setopt($ch, CURLOPT_HEADER, false);
598
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
599
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
600
        curl_setopt($ch, CURLOPT_POST, true);
601
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parameters));
602
        $rs = curl_exec($ch);
603
604
        if (false === $rs) {
605
            throw new Exception(curl_error($ch), curl_errno($ch));
606
        }
607
608
        curl_close($ch);
609
610
        return $rs;
611
    }
612
}
613
614
/**
615
 *  產生訂單.
616
 */
617
class Send extends Aio
618
{
619
    //付款方式物件
620
    public static $PaymentObj;
621
622
    protected static function process($arParameters = [], $arExtend = [])
623
    {
624
        //宣告付款方式物件
625
        $PaymentMethod = 'allPay_'.$arParameters['ChoosePayment'];
626
        self::$PaymentObj = new $PaymentMethod;
627
628
        //檢查參數
629
        $arParameters = self::$PaymentObj->check_string($arParameters);
630
631
        //檢查商品
632
        $arParameters = self::$PaymentObj->check_goods($arParameters);
633
634
        //檢查各付款方式的額外參數&電子發票參數
635
        $arExtend = self::$PaymentObj->check_extend_string($arExtend, $arParameters['InvoiceMark']);
636
637
        //過濾
638
        $arExtend = self::$PaymentObj->filter_string($arExtend, $arParameters['InvoiceMark']);
639
640
        //合併共同參數及延伸參數
641
        return array_merge($arParameters, $arExtend);
642
    }
643
644
    public static function CheckOut($target = '_self', $arParameters = [], $arExtend = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
645
    {
646
        $arParameters = self::process($arParameters, $arExtend);
647
648
        //產生檢查碼
649
        $szCheckMacValue = CheckMacValue::generate($arParameters, $HashKey, $HashIV, $arParameters['EncryptType']);
650
651
        //生成表單,自動送出
652
        $szHtml = '<!DOCTYPE html>';
653
        $szHtml .= '<html>';
654
        $szHtml .= '<head>';
655
        $szHtml .= '<meta charset="utf-8">';
656
        $szHtml .= '</head>';
657
        $szHtml .= '<body>';
658
        $szHtml .= "<form id=\"__allpayForm\" method=\"post\" target=\"{$target}\" action=\"{$ServiceURL}\">";
659
660
        foreach ($arParameters as $keys => $value) {
661
            $szHtml .= "<input type=\"hidden\" name=\"{$keys}\" value=\"{$value}\" />";
662
        }
663
664
        $szHtml .= "<input type=\"hidden\" name=\"CheckMacValue\" value=\"{$szCheckMacValue}\" />";
665
        $szHtml .= '</form>';
666
        $szHtml .= '<script type="text/javascript">document.getElementById("__allpayForm").submit();</script>';
667
        $szHtml .= '</body>';
668
        $szHtml .= '</html>';
669
670
        echo $szHtml;
671
        exit;
672
    }
673
674
    public static function CheckOutString($paymentButton, $target = '_self', $arParameters = [], $arExtend = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
675
    {
676
        $arParameters = self::process($arParameters, $arExtend);
677
678
        //產生檢查碼
679
        $szCheckMacValue = CheckMacValue::generate($arParameters, $HashKey, $HashIV, $arParameters['EncryptType']);
680
681
        $szHtml = '<!DOCTYPE html>';
682
        $szHtml .= '<html>';
683
        $szHtml .= '<head>';
684
        $szHtml .= '<meta charset="utf-8">';
685
        $szHtml .= '</head>';
686
        $szHtml .= '<body>';
687
        $szHtml .= "<form id=\"__allpayForm\" method=\"post\" target=\"{$target}\" action=\"{$ServiceURL}\">";
688
689
        foreach ($arParameters as $keys => $value) {
690
            $szHtml .= "<input type=\"hidden\" name=\"{$keys}\" value=\"{$value}\" />";
691
        }
692
693
        $szHtml .= "<input type=\"hidden\" name=\"CheckMacValue\" value=\"{$szCheckMacValue}\" />";
694
        $szHtml .= "<input type=\"submit\" id=\"__paymentButton\" value=\"{$paymentButton}\" />";
695
        $szHtml .= '</form>';
696
        $szHtml .= '</body>';
697
        $szHtml .= '</html>';
698
699
        return  $szHtml;
700
    }
701
}
702
703
class CheckOutFeedback extends Aio
704
{
705
    public static function CheckOut($arParameters = [], $HashKey = '', $HashIV = '')
706
    {
707
        // 變數宣告。
708
        $arErrors = [];
709
        $arFeedback = [];
710
        $szCheckMacValue = '';
0 ignored issues
show
$szCheckMacValue is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
711
712
        $EncryptType = $arParameters['EncryptType'];
713
        unset($arParameters['EncryptType']);
714
715
        // 重新整理回傳參數。
716
        foreach ($arParameters as $keys => $value) {
717
            if ($keys != 'CheckMacValue') {
718
                if ($keys == 'PaymentType') {
719
                    $value = str_replace('_CVS', '', $value);
720
                    $value = str_replace('_Tenpay', '', $value);
721
                    $value = str_replace('_CreditCard', '', $value);
722
                }
723
                if ($keys == 'PeriodType') {
724
                    $value = str_replace('Y', 'Year', $value);
725
                    $value = str_replace('M', 'Month', $value);
726
                    $value = str_replace('D', 'Day', $value);
727
                }
728
                $arFeedback[$keys] = $value;
729
            }
730
        }
731
732
        $CheckMacValue = CheckMacValue::generate($arParameters, $HashKey, $HashIV, $EncryptType);
733
734
        if ($CheckMacValue != $arParameters['CheckMacValue']) {
735
            array_push($arErrors, 'CheckMacValue verify fail.');
736
        }
737
738
        if (count($arErrors) > 0) {
739
            throw new Exception(implode('- ', $arErrors));
740
        }
741
742
        return $arFeedback;
743
    }
744
}
745
746
class QueryTradeInfo extends Aio
747
{
748
    public static function CheckOut($arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
749
    {
750
        $arErrors = [];
751
        $arParameters['TimeStamp'] = time();
752
        $arFeedback = [];
753
        $arConfirmArgs = [];
754
755
        $EncryptType = $arParameters['EncryptType'];
756
        unset($arParameters['EncryptType']);
757
758
        // 呼叫查詢。
759
        if (count($arErrors) == 0) {
760
            $arParameters['CheckMacValue'] = CheckMacValue::generate($arParameters, $HashKey, $HashIV, $EncryptType);
761
762
            // 送出查詢並取回結果。
763
            $szResult = parent::ServerPost($arParameters, $ServiceURL);
764
            $szResult = str_replace(' ', '%20', $szResult);
765
            $szResult = str_replace('+', '%2B', $szResult);
766
767
            // 轉結果為陣列。
768
            parse_str($szResult, $arResult);
769
770
            // 重新整理回傳參數。
771
            foreach ($arResult as $keys => $value) {
0 ignored issues
show
The expression $arResult of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
772
                if ($keys == 'CheckMacValue') {
773
                    $szCheckMacValue = $value;
774
                } else {
775
                    $arFeedback[$keys] = $value;
776
                    $arConfirmArgs[$keys] = $value;
777
                }
778
            }
779
780
            // 驗證檢查碼。
781
            if (count($arFeedback) > 0) {
782
                $szConfirmMacValue = CheckMacValue::generate($arConfirmArgs, $HashKey, $HashIV, $EncryptType);
783
                if ($szCheckMacValue != $szConfirmMacValue) {
784
                    array_push($arErrors, 'CheckMacValue verify fail.');
785
                }
786
            }
787
        }
788
789
        if (count($arErrors) > 0) {
790
            throw new Exception(implode('- ', $arErrors));
791
        }
792
793
        return $arFeedback;
794
    }
795
}
796
797
class QueryPeriodCreditCardTradeInfo extends Aio
798
{
799
    public static function CheckOut($arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
800
    {
801
        $arErrors = [];
802
        $arParameters['TimeStamp'] = time();
803
        $arFeedback = [];
804
        $arConfirmArgs = [];
0 ignored issues
show
$arConfirmArgs is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
805
806
        $EncryptType = $arParameters['EncryptType'];
807
        unset($arParameters['EncryptType']);
808
809
        // 呼叫查詢。
810
        if (count($arErrors) == 0) {
811
            $arParameters['CheckMacValue'] = CheckMacValue::generate($arParameters, $HashKey, $HashIV, $EncryptType);
812
            // 送出查詢並取回結果。
813
            $szResult = parent::ServerPost($arParameters, $ServiceURL);
814
            $szResult = str_replace(' ', '%20', $szResult);
815
            $szResult = str_replace('+', '%2B', $szResult);
816
817
            // 轉結果為陣列。
818
            $arResult = json_decode($szResult, true);
819
            // 重新整理回傳參數。
820
            foreach ($arResult as $keys => $value) {
821
                $arFeedback[$keys] = $value;
822
            }
823
        }
824
825
        if (count($arErrors) > 0) {
826
            throw new Exception(implode('- ', $arErrors));
827
        }
828
829
        return $arFeedback;
830
    }
831
}
832
833
class DoAction extends Aio
834
{
835
    public static function CheckOut($arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
836
    {
837
        // 變數宣告。
838
        $arErrors = [];
839
        $arFeedback = [];
840
841
        $EncryptType = $arParameters['EncryptType'];
842
        unset($arParameters['EncryptType']);
843
844
        //產生驗證碼
845
        $szCheckMacValue = CheckMacValue::generate($arParameters, $HashKey, $HashIV, $EncryptType);
846
        $arParameters['CheckMacValue'] = $szCheckMacValue;
847
        // 送出查詢並取回結果。
848
        $szResult = self::ServerPost($arParameters, $ServiceURL);
849
        // 轉結果為陣列。
850
        parse_str($szResult, $arResult);
851
        // 重新整理回傳參數。
852
        foreach ($arResult as $keys => $value) {
0 ignored issues
show
The expression $arResult of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
853
            if ($keys == 'CheckMacValue') {
854
                $szCheckMacValue = $value;
855
            } else {
856
                $arFeedback[$keys] = $value;
857
            }
858
        }
859
860
        if (array_key_exists('RtnCode', $arFeedback) && $arFeedback['RtnCode'] != '1') {
861
            array_push($arErrors, vsprintf('#%s: %s', [$arFeedback['RtnCode'], $arFeedback['RtnMsg']]));
862
        }
863
864
        if (count($arErrors) > 0) {
865
            throw new Exception(implode('- ', $arErrors));
866
        }
867
868
        return $arFeedback;
869
    }
870
}
871
872
class AioChargeback extends Aio
873
{
874
    public static function CheckOut($arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
875
    {
876
877
        // 變數宣告。
878
        $arErrors = [];
879
        $arFeedback = [];
880
881
        $EncryptType = $arParameters['EncryptType'];
882
        unset($arParameters['EncryptType']);
883
884
        $szCheckMacValue = CheckMacValue::generate($arParameters, $HashKey, $HashIV, $EncryptType);
885
        $arParameters['CheckMacValue'] = $szCheckMacValue;
886
        // 送出查詢並取回結果。
887
        $szResult = self::ServerPost($arParameters, $ServiceURL);
888
        // 檢查結果資料。
889
        if ($szResult == '1|OK') {
890
            $arFeedback['RtnCode'] = '1';
891
            $arFeedback['RtnMsg'] = 'OK';
892
        } else {
893
            array_push($arErrors, str_replace('-', ': ', $szResult));
894
        }
895
896
        if (count($arErrors) > 0) {
897
            throw new Exception(implode('- ', $arErrors));
898
        }
899
900
        return $arFeedback;
901
    }
902
}
903
904
class AioCapture extends Aio
905
{
906
    public static function Capture($arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
907
    {
908
        $arErrors = [];
909
        $arFeedback = [];
910
911
        $EncryptType = $arParameters['EncryptType'];
912
        unset($arParameters['EncryptType']);
913
914
        $szCheckMacValue = CheckMacValue::generate($arParameters, $HashKey, $HashIV, $EncryptType);
915
        $arParameters['CheckMacValue'] = $szCheckMacValue;
916
917
        // 送出查詢並取回結果。
918
        $szResult = self::ServerPost($arParameters, $ServiceURL);
919
920
        // 轉結果為陣列。
921
        parse_str($szResult, $arResult);
922
923
        // 重新整理回傳參數。
924
        foreach ($arResult as $keys => $value) {
0 ignored issues
show
The expression $arResult of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
925
            $arFeedback[$keys] = $value;
926
        }
927
928
        if (count($arErrors) > 0) {
929
            throw new Exception(implode('- ', $arErrors));
930
        }
931
932
        return $arFeedback;
933
    }
934
}
935
936 View Code Duplication
class TradeNoAio extends Aio
0 ignored issues
show
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
937
{
938
    public static function CheckOut($target = '_self', $arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
939
    {
940
        //產生檢查碼
941
        $EncryptType = $arParameters['EncryptType'];
942
        unset($arParameters['EncryptType']);
943
944
        $szCheckMacValue = CheckMacValue::generate($arParameters, $HashKey, $HashIV, $EncryptType);
945
946
        //生成表單,自動送出
947
        $szHtml = '<!DOCTYPE html>';
948
        $szHtml .= '<html>';
949
        $szHtml .= '<head>';
950
        $szHtml .= '<meta charset="utf-8">';
951
        $szHtml .= '</head>';
952
        $szHtml .= '<body>';
953
        $szHtml .= "<form id=\"__allpayForm\" method=\"post\" target=\"{$target}\" action=\"{$ServiceURL}\">";
954
955
        foreach ($arParameters as $keys => $value) {
956
            $szHtml .= "<input type=\"hidden\" name=\"{$keys}\" value=\"{$value}\" />";
957
        }
958
959
        $szHtml .= "<input type=\"hidden\" name=\"CheckMacValue\" value=\"{$szCheckMacValue}\" />";
960
        $szHtml .= '</form>';
961
        $szHtml .= '<script type="text/javascript">document.getElementById("__allpayForm").submit();</script>';
962
        $szHtml .= '</body>';
963
        $szHtml .= '</html>';
964
965
        echo $szHtml;
966
        exit;
967
    }
968
}
969
970
class QueryTrade extends Aio
971
{
972
    public static function CheckOut($arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
973
    {
974
        $arErrors = [];
975
        $arFeedback = [];
976
        $arConfirmArgs = [];
0 ignored issues
show
$arConfirmArgs is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
977
978
        $EncryptType = $arParameters['EncryptType'];
979
        unset($arParameters['EncryptType']);
980
981
        // 呼叫查詢。
982
        if (count($arErrors) == 0) {
983
            $arParameters['CheckMacValue'] = CheckMacValue::generate($arParameters, $HashKey, $HashIV, $EncryptType);
984
            // 送出查詢並取回結果。
985
            $szResult = parent::ServerPost($arParameters, $ServiceURL);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (ServerPost() instead of CheckOut()). Are you sure this is correct? If so, you might want to change this to $this->ServerPost().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
986
987
            // 轉結果為陣列。
988
            $arResult = json_decode($szResult, true);
989
990
            // 重新整理回傳參數。
991
            foreach ($arResult as $keys => $value) {
992
                $arFeedback[$keys] = $value;
993
            }
994
        }
995
996
        if (count($arErrors) > 0) {
997
            throw new Exception(implode('- ', $arErrors));
998
        }
999
1000
        return $arFeedback;
1001
    }
1002
}
1003
1004 View Code Duplication
class FundingReconDetail extends Aio
0 ignored issues
show
This class seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1005
{
1006
    public static function CheckOut($target = '_self', $arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
1007
    {
1008
        //產生檢查碼
1009
        $EncryptType = $arParameters['EncryptType'];
1010
        unset($arParameters['EncryptType']);
1011
1012
        $szCheckMacValue = CheckMacValue::generate($arParameters, $HashKey, $HashIV, $EncryptType);
1013
1014
        //生成表單,自動送出
1015
        $szHtml = '<!DOCTYPE html>';
1016
        $szHtml .= '<html>';
1017
        $szHtml .= '<head>';
1018
        $szHtml .= '<meta charset="utf-8">';
1019
        $szHtml .= '</head>';
1020
        $szHtml .= '<body>';
1021
        $szHtml .= "<form id=\"__allpayForm\" method=\"post\" target=\"{$target}\" action=\"{$ServiceURL}\">";
1022
1023
        foreach ($arParameters as $keys => $value) {
1024
            $szHtml .= "<input type=\"hidden\" name=\"{$keys}\" value=\"{$value}\" />";
1025
        }
1026
1027
        $szHtml .= "<input type=\"hidden\" name=\"CheckMacValue\" value=\"{$szCheckMacValue}\" />";
1028
        $szHtml .= '</form>';
1029
        $szHtml .= '<script type="text/javascript">document.getElementById("__allpayForm").submit();</script>';
1030
        $szHtml .= '</body>';
1031
        $szHtml .= '</html>';
1032
1033
        echo $szHtml;
1034
        exit;
1035
    }
1036
}
1037
1038
abstract class Verification
1039
{
1040
    // 付款方式延伸參數
1041
    public $arPayMentExtend = [];
1042
1043
    // 電子發票延伸參數。
1044
    public $arInvoice = [
1045
            'RelateNumber',
1046
            'CustomerIdentifier',
1047
            'CarruerType',
1048
            'CustomerID',
1049
            'Donation',
1050
            'Print',
1051
            'TaxType',
1052
            'CustomerName',
1053
            'CustomerAddr',
1054
            'CustomerPhone',
1055
            'CustomerEmail',
1056
            'ClearanceMark',
1057
            'CarruerNum',
1058
            'LoveCode',
1059
            'InvoiceRemark',
1060
            'DelayDay',
1061
            'InvoiceItemName',
1062
            'InvoiceItemCount',
1063
            'InvoiceItemWord',
1064
            'InvoiceItemPrice',
1065
            'InvoiceItemTaxType',
1066
            'InvType',
1067
        ];
1068
1069
    //檢查共同參數
1070
    public function check_string($arParameters = [])
1071
    {
1072
        $arErrors = [];
1073
1074
        if (strlen($arParameters['MerchantID']) == 0) {
1075
            array_push($arErrors, 'MerchantID is required.');
1076
        }
1077
        if (strlen($arParameters['MerchantID']) > 10) {
1078
            array_push($arErrors, 'MerchantID max langth as 10.');
1079
        }
1080
        if (strlen($arParameters['ReturnURL']) == 0) {
1081
            array_push($arErrors, 'ReturnURL is required.');
1082
        }
1083
        if (strlen($arParameters['ClientBackURL']) > 200) {
1084
            array_push($arErrors, 'ClientBackURL max langth as 10.');
1085
        }
1086
        if (strlen($arParameters['OrderResultURL']) > 200) {
1087
            array_push($arErrors, 'OrderResultURL max langth as 10.');
1088
        }
1089
        if (strlen($arParameters['MerchantTradeNo']) == 0) {
1090
            array_push($arErrors, 'MerchantTradeNo is required.');
1091
        }
1092
        if (strlen($arParameters['MerchantTradeNo']) > 20) {
1093
            array_push($arErrors, 'MerchantTradeNo max langth as 20.');
1094
        }
1095
        if (strlen($arParameters['MerchantTradeDate']) == 0) {
1096
            array_push($arErrors, 'MerchantTradeDate is required.');
1097
        }
1098
        if (strlen($arParameters['TotalAmount']) == 0) {
1099
            array_push($arErrors, 'TotalAmount is required.');
1100
        }
1101
        if (strlen($arParameters['TradeDesc']) == 0) {
1102
            array_push($arErrors, 'TradeDesc is required.');
1103
        }
1104
        if (strlen($arParameters['TradeDesc']) > 200) {
1105
            array_push($arErrors, 'TradeDesc max langth as 200.');
1106
        }
1107
        if (strlen($arParameters['ChoosePayment']) == 0) {
1108
            array_push($arErrors, 'ChoosePayment is required.');
1109
        }
1110
        if (strlen($arParameters['NeedExtraPaidInfo']) == 0) {
1111
            array_push($arErrors, 'NeedExtraPaidInfo is required.');
1112
        }
1113
        if (count($arParameters['Items']) == 0) {
1114
            array_push($arErrors, 'Items is required.');
1115
        }
1116
1117
        // 檢查CheckMacValue加密方式
1118
        if (strlen($arParameters['EncryptType']) > 1) {
1119
            array_push($arErrors, 'EncryptType max langth as 1.');
1120
        }
1121
1122
        if (count($arErrors) > 0) {
1123
            throw new Exception(implode('<br>', $arErrors));
1124
        }
1125
        if (! $arParameters['PlatformID']) {
1126
            unset($arParameters['PlatformID']);
1127
        }
1128
1129
        if ($arParameters['ChoosePayment'] !== 'ALL') {
1130
            unset($arParameters['IgnorePayment']);
1131
        }
1132
1133
        return $arParameters;
1134
    }
1135
1136
    //檢查商品
1137
    public function check_goods($arParameters = [])
1138
    {
1139
        // 檢查產品名稱。
1140
        $arErrors = [];
1141
        $szItemName = '';
1142
1143
        if (count($arParameters['Items']) > 0) {
1144
            foreach ($arParameters['Items'] as $keys => $value) {
1145
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1146
                if (! array_key_exists('ItemURL', $arParameters)) {
1147
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1148
                }
1149
            }
1150
1151
            if (strlen($szItemName) > 0) {
1152
                $szItemName = mb_substr($szItemName, 1, 200);
1153
                $arParameters['ItemName'] = $szItemName;
1154
            }
1155
        } else {
1156
            array_push($arErrors, 'Goods information not found.');
1157
        }
1158
1159
        if (count($arErrors) > 0) {
1160
            throw new Exception(implode('<br>', $arErrors));
1161
        }
1162
        unset($arParameters['Items']);
1163
1164
        return $arParameters;
1165
    }
1166
1167
    //過濾多餘參數
1168
    public function filter_string($arExtend = [], $InvoiceMark = '')
1169
    {
1170
        $arPayMentExtend = array_merge(array_keys($this->arPayMentExtend), ($InvoiceMark == '') ? [] : $this->arInvoice);
1171
1172
        foreach ($arExtend as $key => $value) {
1173
            if (! in_array($key, $arPayMentExtend)) {
1174
                unset($arExtend[$key]);
1175
            }
1176
        }
1177
1178
        return $arExtend;
1179
    }
1180
1181
    //檢查預設參數
1182
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1183
    {
1184
        //沒設定參數的話,就給預設參數
1185
        foreach ($this->arPayMentExtend as $key => $value) {
1186
            if (! isset($arExtend[$key])) {
1187
                $arExtend[$key] = $value;
1188
            }
1189
        }
1190
1191
        //若有開發票,檢查一下發票參數
1192
        if ($InvoiceMark == 'Y') {
1193
            $arExtend = $this->check_invoiceString($arExtend);
1194
        }
1195
1196
        return $arExtend;
1197
    }
1198
1199
    //檢查電子發票參數
1200
    public function check_invoiceString($arExtend = [])
1201
    {
1202
        $arErrors = [];
1203
1204
        // 廠商自訂編號RelateNumber(不可為空)
1205 View Code Duplication
        if (! array_key_exists('RelateNumber', $arExtend)) {
1206
            array_push($arErrors, 'RelateNumber is required.');
1207
        } else {
1208
            if (strlen($arExtend['RelateNumber']) > 30) {
1209
                array_push($arErrors, 'RelateNumber max length as 30.');
1210
            }
1211
        }
1212
1213
        // 統一編號CustomerIdentifier(預設為空字串)
1214 View Code Duplication
        if (! array_key_exists('CustomerIdentifier', $arExtend)) {
1215
            $arExtend['CustomerIdentifier'] = '';
1216
        } else {
1217
            //統編長度只能為8
1218
            if (strlen($arExtend['CustomerIdentifier']) != 8) {
1219
                array_push($arErrors, 'CustomerIdentifier length should be 8.');
1220
            }
1221
        }
1222
1223
        // 載具類別CarruerType(預設為None)
1224
        if (! array_key_exists('CarruerType', $arExtend)) {
1225
            $arExtend['CarruerType'] = CarruerType::None;
1226
        } else {
1227
            //有設定統一編號的話,載具類別不可為合作特店載具或自然人憑證載具。
1228
            $notPrint = [CarruerType::Member, CarruerType::Citizen];
1229
            if (strlen($arExtend['CustomerIdentifier']) > 0 && in_array($arExtend['CarruerType'], $notPrint)) {
1230
                array_push($arErrors, 'CarruerType should NOT be Member or Citizen.');
1231
            }
1232
        }
1233
1234
        // 客戶代號CustomerID(預設為空字串)
1235 View Code Duplication
        if (! array_key_exists('CustomerID', $arExtend)) {
1236
            $arExtend['CustomerID'] = '';
1237
        } else {
1238
            if ($arExtend['CarruerType'] == CarruerType::Member && strlen($arExtend['CustomerID']) == 0) {
1239
                array_push($arErrors, 'CustomerID is required.');
1240
            }
1241
        }
1242
        // 捐贈註記 Donation(預設為No)
1243 View Code Duplication
        if (! array_key_exists('Donation', $arExtend)) {
1244
            $arExtend['Donation'] = Donation::No;
1245
        } else {
1246
            //若有帶統一編號,不可捐贈
1247
            if (strlen($arExtend['CustomerIdentifier']) > 0 && $arExtend['Donation'] != Donation::No) {
1248
                array_push($arErrors, 'Donation should be No.');
1249
            }
1250
        }
1251
1252
        // 列印註記Print(預設為No)
1253 View Code Duplication
        if (! array_key_exists('Print', $arExtend)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1254
            $arExtend['Print'] = PrintMark::No;
1255
        } else {
1256
            //捐贈註記為捐贈(Yes)時,請設定不列印(No)
1257
            if ($arExtend['Donation'] == Donation::Yes && $arExtend['Print'] != PrintMark::No) {
1258
                array_push($arErrors, 'Print should be No.');
1259
            }
1260
            // 統一編號不為空字串時,請設定列印(Yes)
1261
            if (strlen($arExtend['CustomerIdentifier']) > 0 && $arExtend['Print'] != PrintMark::Yes) {
1262
                array_push($arErrors, 'Print should be Yes.');
1263
            }
1264
        }
1265
        // 客戶名稱CustomerName(UrlEncode, 預設為空字串)
1266 View Code Duplication
        if (! array_key_exists('CustomerName', $arExtend)) {
1267
            $arExtend['CustomerName'] = '';
1268
        } else {
1269
            if (mb_strlen($arExtend['CustomerName'], 'UTF-8') > 20) {
1270
                array_push($arErrors, 'CustomerName max length as 20.');
1271
            }
1272
            // 列印註記為列印(Yes)時,此參數不可為空字串
1273
            if ($arExtend['Print'] == PrintMark::Yes && strlen($arExtend['CustomerName']) == 0) {
1274
                array_push($arErrors, 'CustomerName is required.');
1275
            }
1276
        }
1277
1278
        // 客戶地址CustomerAddr(UrlEncode, 預設為空字串)
1279 View Code Duplication
        if (! array_key_exists('CustomerAddr', $arExtend)) {
1280
            $arExtend['CustomerAddr'] = '';
1281
        } else {
1282
            if (mb_strlen($arExtend['CustomerAddr'], 'UTF-8') > 200) {
1283
                array_push($arErrors, 'CustomerAddr max length as 200.');
1284
            }
1285
            // 列印註記為列印(Yes)時,此參數不可為空字串
1286
            if ($arExtend['Print'] == PrintMark::Yes && strlen($arExtend['CustomerAddr']) == 0) {
1287
                array_push($arErrors, 'CustomerAddr is required.');
1288
            }
1289
        }
1290
        // 客戶電話CustomerPhone
1291 View Code Duplication
        if (! array_key_exists('CustomerPhone', $arExtend)) {
1292
            $arExtend['CustomerPhone'] = '';
1293
        } else {
1294
            if (strlen($arExtend['CustomerPhone']) > 20) {
1295
                array_push($arErrors, 'CustomerPhone max length as 20.');
1296
            }
1297
        }
1298
1299
        // 客戶信箱CustomerEmail
1300 View Code Duplication
        if (! array_key_exists('CustomerEmail', $arExtend)) {
1301
            $arExtend['CustomerEmail'] = '';
1302
        } else {
1303
            if (strlen($arExtend['CustomerEmail']) > 200) {
1304
                array_push($arErrors, 'CustomerEmail max length as 200.');
1305
            }
1306
        }
1307
1308
        //(CustomerEmail與CustomerPhone擇一不可為空)
1309
        if (strlen($arExtend['CustomerPhone']) == 0 and strlen($arExtend['CustomerEmail']) == 0) {
1310
            array_push($arErrors, 'CustomerPhone or CustomerEmail is required.');
1311
        }
1312
1313
        //課稅類別 TaxType(不可為空)
1314
        if (strlen($arExtend['TaxType']) == 0) {
1315
            array_push($arErrors, 'TaxType is required.');
1316
        }
1317
1318
        //通關方式 ClearanceMark(預設為空字串)
1319 View Code Duplication
        if (! array_key_exists('ClearanceMark', $arExtend)) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1320
            $arExtend['ClearanceMark'] = '';
1321
        } else {
1322
            //課稅類別為零稅率(Zero)時,ClearanceMark不可為空字串
1323
            if ($arExtend['TaxType'] == TaxType::Zero && ($arExtend['ClearanceMark'] != ClearanceMark::Yes || $arExtend['ClearanceMark'] != ClearanceMark::No)) {
1324
                array_push($arErrors, 'ClearanceMark is required.');
1325
            }
1326
            if (strlen($arExtend['ClearanceMark']) > 0 && $arExtend['TaxType'] != TaxType::Zero) {
1327
                array_push($arErrors, 'Please remove ClearanceMark.');
1328
            }
1329
        }
1330
1331
        // CarruerNum(預設為空字串)
1332
        if (! array_key_exists('CarruerNum', $arExtend)) {
1333
            $arExtend['CarruerNum'] = '';
1334
        } else {
1335
            switch ($arExtend['CarruerType']) {
1336
                // 載具類別為無載具(None)或會員載具(Member)時,系統自動忽略載具編號
1337
                case CarruerType::None:
1338
                case CarruerType::Member:
1339
                break;
1340
                // 載具類別為買受人自然人憑證(Citizen)時,請設定自然人憑證號碼,前2碼為大小寫英文,後14碼為數字
1341 View Code Duplication
                case CarruerType::Citizen:
1342
                    if (! preg_match('/^[a-zA-Z]{2}\d{14}$/', $arExtend['CarruerNum'])) {
1343
                        array_push($arErrors, 'Invalid CarruerNum.');
1344
                    }
1345
                break;
1346
                // 載具類別為買受人手機條碼(Cellphone)時,請設定手機條碼,第1碼為「/」,後7碼為大小寫英文、數字、「+」、「-」或「.」
1347 View Code Duplication
                case CarruerType::Cellphone:
1348
                    if (! preg_match('/^\/{1}[0-9a-zA-Z+-.]{7}$/', $arExtend['CarruerNum'])) {
1349
                        array_push($arErrors, 'Invalid CarruerNum.');
1350
                    }
1351
                break;
1352
1353
                default:
1354
                    array_push($arErrors, 'Please remove CarruerNum.');
1355
            }
1356
        }
1357
1358
        // 愛心碼 LoveCode(預設為空字串)
1359
        if (! array_key_exists('LoveCode', $arExtend)) {
1360
            $arExtend['LoveCode'] = '';
1361
        }
1362
        // 捐贈註記為捐贈(Yes)時,參數長度固定3~7碼,請設定全數字或第1碼大小寫「X」,後2~6碼全數字
1363
        if ($arExtend['Donation'] == Donation::Yes) {
1364
            if (! preg_match('/^([xX]{1}[0-9]{2,6}|[0-9]{3,7})$/', $arExtend['LoveCode'])) {
1365
                array_push($arErrors, 'Invalid LoveCode.');
1366
            }
1367
        }
1368
1369
        //備註 InvoiceRemark(UrlEncode, 預設為空字串)
1370
        if (! array_key_exists('InvoiceRemark', $arExtend)) {
1371
            $arExtend['InvoiceRemark'] = '';
1372
        }
1373
1374
        // 延遲天數 DelayDay(不可為空, 預設為0) 延遲天數,範圍0~15,設定為0時,付款完成後立即開立發票
1375
        if (! array_key_exists('DelayDay', $arExtend)) {
1376
            $arExtend['DelayDay'] = 0;
1377
        }
1378
        if ($arExtend['DelayDay'] < 0 or $arExtend['DelayDay'] > 15) {
1379
            array_push($arErrors, 'DelayDay should be 0 ~ 15.');
1380
        }
1381
1382
        // 字軌類別 InvType(不可為空)
1383
        if (! array_key_exists('InvType', $arExtend)) {
1384
            array_push($arErrors, 'InvType is required.');
1385
        }
1386
1387
        //商品相關整理
1388
        if (! array_key_exists('InvoiceItems', $arExtend)) {
1389
            array_push($arErrors, 'Invoice Goods information not found.');
1390
        } else {
1391
            $InvSptr = '|';
1392
            $tmpItemName = [];
1393
            $tmpItemCount = [];
1394
            $tmpItemWord = [];
1395
            $tmpItemPrice = [];
1396
            $tmpItemTaxType = [];
1397
            foreach ($arExtend['InvoiceItems'] as $tmpItemInfo) {
1398
                if (mb_strlen($tmpItemInfo['Name'], 'UTF-8') > 0) {
1399
                    array_push($tmpItemName, $tmpItemInfo['Name']);
1400
                }
1401
                if (strlen($tmpItemInfo['Count']) > 0) {
1402
                    array_push($tmpItemCount, $tmpItemInfo['Count']);
1403
                }
1404
                if (mb_strlen($tmpItemInfo['Word'], 'UTF-8') > 0) {
1405
                    array_push($tmpItemWord, $tmpItemInfo['Word']);
1406
                }
1407
                if (strlen($tmpItemInfo['Price']) > 0) {
1408
                    array_push($tmpItemPrice, $tmpItemInfo['Price']);
1409
                }
1410
                if (strlen($tmpItemInfo['TaxType']) > 0) {
1411
                    array_push($tmpItemTaxType, $tmpItemInfo['TaxType']);
1412
                }
1413
            }
1414
1415
            if ($arExtend['TaxType'] == TaxType::Mix) {
1416
                if (in_array(TaxType::Dutiable, $tmpItemTaxType) and in_array(TaxType::Free, $tmpItemTaxType)) {
1417
                    // Do nothing
1418
                } else {
1419
                    $tmpItemTaxType = [];
1420
                }
1421
            }
1422
            if ((count($tmpItemName) + count($tmpItemCount) + count($tmpItemWord) + count($tmpItemPrice) + count($tmpItemTaxType)) == (count($tmpItemName) * 5)) {
1423
                $arExtend['InvoiceItemName'] = implode($InvSptr, $tmpItemName);
1424
                $arExtend['InvoiceItemCount'] = implode($InvSptr, $tmpItemCount);
1425
                $arExtend['InvoiceItemWord'] = implode($InvSptr, $tmpItemWord);
1426
                $arExtend['InvoiceItemPrice'] = implode($InvSptr, $tmpItemPrice);
1427
                $arExtend['InvoiceItemTaxType'] = implode($InvSptr, $tmpItemTaxType);
1428
            }
1429
1430
            unset($arExtend['InvoiceItems']);
1431
        }
1432
1433
        $encode_fields = [
1434
                'CustomerName',
1435
                'CustomerAddr',
1436
                'CustomerEmail',
1437
                'InvoiceItemName',
1438
                'InvoiceItemWord',
1439
                'InvoiceRemark',
1440
            ];
1441
        foreach ($encode_fields as $tmp_field) {
1442
            $arExtend[$tmp_field] = urlencode($arExtend[$tmp_field]);
1443
        }
1444
1445
        if (count($arErrors) > 0) {
1446
            throw new Exception(implode('<br>', $arErrors));
1447
        }
1448
1449
        return $arExtend;
1450
    }
1451
}
1452
1453
/**
1454
 *  付款方式:超商代碼
1455
 */
1456
class allPay_CVS extends Verification
1457
{
1458
    public $arPayMentExtend = [
1459
                            'Desc_1'           =>'',
1460
                            'Desc_2'           =>'',
1461
                            'Desc_3'           =>'',
1462
                            'Desc_4'           =>'',
1463
                            'PaymentInfoURL'   =>'',
1464
                            'ClientRedirectURL'=>'',
1465
                            'StoreExpireDate'  =>'',
1466
                        ];
1467
1468
    //過濾多餘參數
1469
    public function filter_string($arExtend = [], $InvoiceMark = '')
1470
    {
1471
        $arExtend = parent::filter_string($arExtend, $InvoiceMark);
1472
1473
        return $arExtend;
1474
    }
1475
}
1476
1477
/**
1478
 *  付款方式 ATM.
1479
 */
1480
class allPay_ATM extends Verification
1481
{
1482
    public $arPayMentExtend = [
1483
                            'ExpireDate'       => 3,
1484
                            'PaymentInfoURL'   => '',
1485
                            'ClientRedirectURL'=> '',
1486
                        ];
1487
1488
    //過濾多餘參數
1489
    public function filter_string($arExtend = [], $InvoiceMark = '')
1490
    {
1491
        $arExtend = parent::filter_string($arExtend, $InvoiceMark);
1492
1493
        return $arExtend;
1494
    }
1495
}
1496
1497
/**
1498
 *  付款方式 WebATM.
1499
 */
1500
class allPay_WebATM extends Verification
1501
{
1502
    public $arPayMentExtend = [];
1503
1504
    //過濾多餘參數
1505
    public function filter_string($arExtend = [], $InvoiceMark = '')
1506
    {
1507
        $arExtend = parent::filter_string($arExtend, $InvoiceMark);
1508
1509
        return $arExtend;
1510
    }
1511
}
1512
1513
/**
1514
 * 付款方式:Tenpay.
1515
 */
1516
class allPay_Tenpay extends Verification
1517
{
1518
    public $arPayMentExtend = ['ExpireTime' => ''];
1519
1520
    //過濾多餘參數
1521
    public function filter_string($arExtend = [], $InvoiceMark = '')
1522
    {
1523
        $arExtend = parent::filter_string($arExtend, $InvoiceMark);
1524
1525
        return $arExtend;
1526
    }
1527
}
1528
1529
/**
1530
 * 付款方式 : 信用卡
1531
 */
1532
class allPay_Credit extends Verification
1533
{
1534
    public $arPayMentExtend = [
1535
                                    'CreditInstallment' => '',
1536
                                    'InstallmentAmount' => 0,
1537
                                    'Redeem'            => false,
1538
                                    'PeriodAmount'      => '',
1539
                                    'PeriodType'        => '',
1540
                                    'Frequency'         => '',
1541
                                    'ExecTimes'         => '',
1542
                                    'PeriodReturnURL'   => '',
1543
                                ];
1544
1545
    //過濾多餘參數
1546
    public function filter_string($arExtend = [], $InvoiceMark = '')
1547
    {
1548
        $arExtend = parent::filter_string($arExtend, $InvoiceMark);
1549
1550
        return $arExtend;
1551
    }
1552
}
1553
1554
/**
1555
 * 付款方式:TopUpUsed.
1556
 */
1557
class allPay_TopUpUsed extends Verification
1558
{
1559
    public $arPayMentExtend = [];
1560
1561
    //過濾多餘參數
1562
    public function filter_string($arExtend = [], $InvoiceMark = '')
1563
    {
1564
        return $arExtend;
1565
    }
1566
}
1567
1568
/**
1569
 *  付款方式:全功能.
1570
 */
1571
class allPay_ALL extends Verification
1572
{
1573
    public $arPayMentExtend = [];
1574
1575
    //過濾多餘參數
1576
    public function filter_string($arExtend = [], $InvoiceMark = '')
1577
    {
1578
        return $arExtend;
1579
    }
1580
}
1581
1582
/**
1583
 *  檢查碼
1584
 */
1585
class CheckMacValue
1586
{
1587
    public static function generate($arParameters = [], $HashKey = '', $HashIV = '', $encType = 0)
1588
    {
1589
        $sMacValue = '';
1590
1591
        if (isset($arParameters)) {
1592
            unset($arParameters['CheckMacValue']);
1593
            uksort($arParameters, ['CheckMacValue', 'merchantSort']);
1594
1595
            // 組合字串
1596
            $sMacValue = 'HashKey='.$HashKey;
1597
            foreach ($arParameters as $key => $value) {
1598
                $sMacValue .= '&'.$key.'='.$value;
1599
            }
1600
1601
            $sMacValue .= '&HashIV='.$HashIV;
1602
1603
            // URL Encode編碼
1604
            $sMacValue = urlencode($sMacValue);
1605
1606
            // 轉成小寫
1607
            $sMacValue = strtolower($sMacValue);
1608
1609
            // 取代為與 dotNet 相符的字元
1610
            $sMacValue = str_replace('%2d', '-', $sMacValue);
1611
            $sMacValue = str_replace('%5f', '_', $sMacValue);
1612
            $sMacValue = str_replace('%2e', '.', $sMacValue);
1613
            $sMacValue = str_replace('%21', '!', $sMacValue);
1614
            $sMacValue = str_replace('%2a', '*', $sMacValue);
1615
            $sMacValue = str_replace('%28', '(', $sMacValue);
1616
            $sMacValue = str_replace('%29', ')', $sMacValue);
1617
1618
            // 編碼
1619
            switch ($encType) {
1620
                case EncryptType::ENC_SHA256:
1621
                    // SHA256 編碼
1622
                    $sMacValue = hash('sha256', $sMacValue);
1623
                break;
1624
1625
                case EncryptType::ENC_MD5:
1626
                default:
1627
                // MD5 編碼
1628
                    $sMacValue = md5($sMacValue);
1629
            }
1630
1631
            $sMacValue = strtoupper($sMacValue);
1632
        }
1633
1634
        return $sMacValue;
1635
    }
1636
1637
    /**
1638
     * 自訂排序使用.
1639
     */
1640
    private static function merchantSort($a, $b)
1641
    {
1642
        return strcasecmp($a, $b);
1643
    }
1644
}
1645