ECPay_Verification::check_string()   F
last analyzed

Complexity

Conditions 17
Paths > 20000

Size

Total Lines 57
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 57
rs 3.3193
c 0
b 0
f 0
cc 17
eloc 34
nc 65536
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * 付款方式。
5
 */
6
abstract class ECPay_PaymentMethod
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
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 BARCODE = 'BARCODE';
37
}
38
39
/**
40
 * 付款方式子項目。
41
 */
42
abstract class ECPay_PaymentMethodItem
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
43
{
44
    /**
45
     * 不指定。
46
     */
47
    const None = '';
48
    // WebATM 類(001~100)
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
49
    /**
50
     * 台新銀行。
51
     */
52
    const WebATM_TAISHIN = 'TAISHIN';
53
54
    /**
55
     * 玉山銀行。
56
     */
57
    const WebATM_ESUN = 'ESUN';
58
59
    /**
60
     * 華南銀行。
61
     */
62
    const WebATM_HUANAN = 'HUANAN';
63
64
    /**
65
     * 台灣銀行。
66
     */
67
    const WebATM_BOT = 'BOT';
68
69
    /**
70
     * 台北富邦。
71
     */
72
    const WebATM_FUBON = 'FUBON';
73
74
    /**
75
     * 中國信託。
76
     */
77
    const WebATM_CHINATRUST = 'CHINATRUST';
78
79
    /**
80
     * 第一銀行。
81
     */
82
    const WebATM_FIRST = 'FIRST';
83
84
    /**
85
     * 國泰世華。
86
     */
87
    const WebATM_CATHAY = 'CATHAY';
88
89
    /**
90
     * 兆豐銀行。
91
     */
92
    const WebATM_MEGA = 'MEGA';
93
94
    /**
95
     * 元大銀行。
96
     */
97
    const WebATM_YUANTA = 'YUANTA';
98
99
    /**
100
     * 土地銀行。
101
     */
102
    const WebATM_LAND = 'LAND';
103
    // ATM 類(101~200)
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
104
    /**
105
     * 台新銀行。
106
     */
107
    const ATM_TAISHIN = 'TAISHIN';
108
109
    /**
110
     * 玉山銀行。
111
     */
112
    const ATM_ESUN = 'ESUN';
113
114
    /**
115
     * 華南銀行。
116
     */
117
    const ATM_HUANAN = 'HUANAN';
118
119
    /**
120
     * 台灣銀行。
121
     */
122
    const ATM_BOT = 'BOT';
123
124
    /**
125
     * 台北富邦。
126
     */
127
    const ATM_FUBON = 'FUBON';
128
129
    /**
130
     * 中國信託。
131
     */
132
    const ATM_CHINATRUST = 'CHINATRUST';
133
134
    /**
135
     * 土地銀行。
136
     */
137
    const ATM_LAND = 'LAND';
138
139
    /**
140
     * 國泰世華銀行。
141
     */
142
    const ATM_CATHAY = 'CATHAY';
143
144
    /**
145
     * 大眾銀行。
146
     */
147
    const ATM_Tachong = 'Tachong';
148
149
    /**
150
     * 永豐銀行。
151
     */
152
    const ATM_Sinopac = 'Sinopac';
153
154
    /**
155
     * 彰化銀行。
156
     */
157
    const ATM_CHB = 'CHB';
158
159
    /**
160
     * 第一銀行。
161
     */
162
    const ATM_FIRST = 'FIRST';
163
164
    // 超商類(201~300)
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
165
    /**
166
     * 超商代碼繳款。
167
     */
168
    const CVS = 'CVS';
169
170
    /**
171
     * OK超商代碼繳款。
172
     */
173
    const CVS_OK = 'OK';
174
175
    /**
176
     * 全家超商代碼繳款。
177
     */
178
    const CVS_FAMILY = 'FAMILY';
179
180
    /**
181
     * 萊爾富超商代碼繳款。
182
     */
183
    const CVS_HILIFE = 'HILIFE';
184
185
    /**
186
     * 7-11 ibon代碼繳款。
187
     */
188
    const CVS_IBON = 'IBON';
189
190
    // 其他類(901~999)
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
191
    /**
192
     * 超商條碼繳款。
193
     */
194
    const BARCODE = 'BARCODE';
195
196
    /**
197
     * 信用卡(MasterCard/JCB/VISA)。
198
     */
199
    const Credit = 'Credit';
200
201
    /**
202
     * 貨到付款。
203
     */
204
    const COD = 'COD';
205
}
206
207
/**
208
 * 額外付款資訊。
209
 */
210
abstract class ECPay_ExtraPaymentInfo
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
211
{
212
    /**
213
     * 需要額外付款資訊。
214
     */
215
    const Yes = 'Y';
216
217
    /**
218
     * 不需要額外付款資訊。
219
     */
220
    const No = 'N';
221
}
222
223
/**
224
 * 額外付款資訊。
225
 */
226
abstract class ECPay_DeviceType
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
227
{
228
    /**
229
     * 桌機版付費頁面。
230
     */
231
    const PC = 'P';
232
233
    /**
234
     * 行動裝置版付費頁面。
235
     */
236
    const Mobile = 'M';
237
}
238
239
/**
240
 * 信用卡訂單處理動作資訊。
241
 */
242
abstract class ECPay_ActionType
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
243
{
244
    /**
245
     * 關帳.
246
     */
247
    const C = 'C';
248
249
    /**
250
     * 退刷.
251
     */
252
    const R = 'R';
253
254
    /**
255
     * 取消.
256
     */
257
    const E = 'E';
258
259
    /**
260
     * 放棄.
261
     */
262
    const N = 'N';
263
}
264
265
/**
266
 * 定期定額的週期種類。
267
 */
268
abstract class ECPay_PeriodType
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
269
{
270
    /**
271
     * 無
272
     */
273
    const None = '';
274
275
    /**
276
     * 年.
277
     */
278
    const Year = 'Y';
279
280
    /**
281
     * 月.
282
     */
283
    const Month = 'M';
284
285
    /**
286
     * 日.
287
     */
288
    const Day = 'D';
289
}
290
291
/**
292
 * 電子發票開立註記。
293
 */
294
abstract class ECPay_InvoiceState
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
295
{
296
    /**
297
     * 需要開立電子發票。
298
     */
299
    const Yes = 'Y';
300
301
    /**
302
     * 不需要開立電子發票。
303
     */
304
    const No = '';
305
}
306
307
/**
308
 * 電子發票載具類別.
309
 */
310
abstract class ECPay_CarrierType
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
311
{
312
    // 無載具
313
    const None = '';
314
315
    // 會員載具
316
    const Member = '1';
317
318
    // 買受人自然人憑證
319
    const Citizen = '2';
320
321
    // 買受人手機條碼
322
    const Cellphone = '3';
323
}
324
325
/**
326
 * 電子發票列印註記.
327
 */
328
abstract class ECPay_PrintMark
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
329
{
330
    // 不列印
331
    const No = '0';
332
333
    // 列印
334
    const Yes = '1';
335
}
336
337
/**
338
 * 電子發票捐贈註記.
339
 */
340
abstract class ECPay_Donation
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
341
{
342
    // 捐贈
343
    const Yes = '1';
344
345
    // 不捐贈
346
    const No = '2';
347
}
348
349
/**
350
 * 通關方式.
351
 */
352
abstract class ECPay_ClearanceMark
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
353
{
354
    // 經海關出口
355
    const Yes = '1';
356
357
    // 非經海關出口
358
    const No = '2';
359
}
360
361
/**
362
 * 課稅類別.
363
 */
364
abstract class ECPay_TaxType
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
365
{
366
    // 應稅
367
    const Dutiable = '1';
368
369
    // 零稅率
370
    const Zero = '2';
371
372
    // 免稅
373
    const Free = '3';
374
375
    // 應稅與免稅混合(限收銀機發票無法分辦時使用,且需通過申請核可)
376
    const Mix = '9';
377
}
378
379
/**
380
 * 字軌類別.
381
 */
382
abstract class ECPay_InvType
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
383
{
384
    // 一般稅額
385
    const General = '07';
386
387
    // 特種稅額
388
    const Special = '08';
389
}
390
391
abstract class ECPay_EncryptType
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
392
{
393
    // MD5(預設)
394
    const ENC_MD5 = 0;
395
396
    // SHA256
397
    const ENC_SHA256 = 1;
398
}
399
400
/**
401
 * AllInOne short summary.
402
 *
403
 * AllInOne description.
404
 *
405
 * @version 1.1.0818
406
 * @author charlie
407
 */
408
class ECPay_AllInOne
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
409
{
410
    public $ServiceURL = 'ServiceURL';
411
    public $ServiceMethod = 'ServiceMethod';
412
    public $HashKey = 'HashKey';
413
    public $HashIV = 'HashIV';
414
    public $MerchantID = 'MerchantID';
415
    public $PaymentType = 'PaymentType';
416
    public $Send = 'Send';
417
    public $SendExtend = 'SendExtend';
418
    public $Query = 'Query';
419
    public $Action = 'Action';
420
    public $EncryptType = ECPay_EncryptType::ENC_MD5;
421
422
    public function __construct()
423
    {
424
        $this->PaymentType = 'aio';
425
        $this->Send = [
0 ignored issues
show
Documentation Bug introduced by
It seems like array('ReturnURL' => '',...y_EncryptType::ENC_MD5) of type array<string,string|arra...ring","Items":"array"}> 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...
426
            'ReturnURL' => '',
427
            'ClientBackURL' => '',
428
            'OrderResultURL' => '',
429
            'MerchantTradeNo' => '',
430
            'MerchantTradeDate' => '',
431
            'PaymentType' => 'aio',
432
            'TotalAmount' => '',
433
            'TradeDesc' => '',
434
            'ChoosePayment' => ECPay_PaymentMethod::ALL,
435
            'Remark' => '',
436
            'ChooseSubPayment' => ECPay_PaymentMethodItem::None,
437
            'NeedExtraPaidInfo' => ECPay_ExtraPaymentInfo::No,
438
            'DeviceSource' => '',
439
            'IgnorePayment' => '',
440
            'PlatformID' => '',
441
            'InvoiceMark' => ECPay_InvoiceState::No,
442
            'Items' => [],
443
            'EncryptType' => ECPay_EncryptType::ENC_MD5,
444
        ];
445
446
        $this->SendExtend = [];
0 ignored issues
show
Documentation Bug introduced by
It seems like array() of type array is incompatible with the declared type string of property $SendExtend.

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...
447
448
        $this->Query = [
0 ignored issues
show
Documentation Bug introduced by
It seems like array('MerchantTradeNo' => '', 'TimeStamp' => '') of type array<string,string,{"Me...,"TimeStamp":"string"}> is incompatible with the declared type string of property $Query.

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...
449
            'MerchantTradeNo' => '', 'TimeStamp' => '',
450
        ];
451
        $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...
452
            'MerchantTradeNo' => '', 'TradeNo' => '', 'Action' => ECPay_ActionType::C, 'TotalAmount' => 0,
453
        ];
454
        $this->Capture = [];
0 ignored issues
show
Bug introduced by
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...
455
    }
456
457
    //產生訂單
458
    public function CheckOut($target = '_self')
459
    {
460
        $arParameters = array_merge(['MerchantID' => $this->MerchantID], $this->Send);
461
        ECPay_Send::CheckOut($target, $arParameters, $this->SendExtend, $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
Documentation introduced by
$this->SendExtend is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
462
    }
463
464
    //產生訂單html code
465
    public function CheckOutString($paymentButton = null, $target = '_self')
0 ignored issues
show
Unused Code introduced by
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...
466
    {
467
        $arParameters = array_merge(['MerchantID' => $this->MerchantID], $this->Send);
468
469
        return ECPay_Send::CheckOutString($paymentButton, $target = '_self', $arParameters, $this->SendExtend, $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
Documentation introduced by
$this->SendExtend is of type string, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
470
    }
471
472
    //取得付款結果通知的方法
473
    public function CheckOutFeedback()
0 ignored issues
show
Coding Style introduced by
CheckOutFeedback uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
474
    {
475
        return $arFeedback = ECPay_CheckOutFeedback::CheckOut($_POST, $this->HashKey, $this->HashIV, 0);
0 ignored issues
show
Unused Code introduced by
The call to ECPay_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...
Unused Code introduced by
$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...
476
    }
477
478
    //訂單查詢作業
479
    public function QueryTradeInfo()
480
    {
481
        return $arFeedback = ECPay_QueryTradeInfo::CheckOut(array_merge($this->Query, ['MerchantID' => $this->MerchantID]), $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
Unused Code introduced by
$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...
482
    }
483
484
    //信用卡定期定額訂單查詢的方法
485
    public function QueryPeriodCreditCardTradeInfo()
486
    {
487
        return $arFeedback = ECPay_QueryPeriodCreditCardTradeInfo::CheckOut(array_merge($this->Query, ['MerchantID' => $this->MerchantID]), $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
Unused Code introduced by
$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...
488
    }
489
490
    //信用卡關帳/退刷/取消/放棄的方法
491
    public function DoAction()
492
    {
493
        return $arFeedback = ECPay_DoAction::CheckOut(array_merge($this->Action, ['MerchantID' => $this->MerchantID]), $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
Unused Code introduced by
$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...
494
    }
495
496
    //合作特店申請撥款
497
    public function AioCapture()
498
    {
499
        return $arFeedback = ECPay_AioCapture::Capture(array_merge($this->Capture, ['MerchantID' => $this->MerchantID]), $this->HashKey, $this->HashIV, $this->ServiceURL);
0 ignored issues
show
Unused Code introduced by
$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...
500
    }
501
}
502
503
/**
504
 * 抽象類.
505
 */
506
abstract class ECPay_Aio
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
507
{
508
    protected static function ServerPost($parameters, $ServiceURL)
509
    {
510
        $ch = curl_init();
511
512
        if (false === $ch) {
513
            throw new Exception('curl failed to initialize');
514
        }
515
516
        curl_setopt($ch, CURLOPT_URL, $ServiceURL);
517
        curl_setopt($ch, CURLOPT_HEADER, false);
518
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
519
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
520
        curl_setopt($ch, CURLOPT_POST, true);
521
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($parameters));
522
        $rs = curl_exec($ch);
523
524
        if (false === $rs) {
525
            throw new Exception(curl_error($ch), curl_errno($ch));
526
        }
527
528
        curl_close($ch);
529
530
        return $rs;
531
    }
532
}
533
534
/**
535
 *  產生訂單.
536
 */
537
class ECPay_Send extends ECPay_Aio
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
538
{
539
    //付款方式物件
540
    public static $PaymentObj;
541
542 View Code Duplication
    public static function CheckOut($target = '_self', $arParameters = [], $arExtend = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
0 ignored issues
show
Duplication introduced by
This method 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...
543
    {
544
        $arParameters = self::process($arParameters, $arExtend);
545
        //產生檢查碼
546
        $szCheckMacValue = ECPay_CheckMacValue::generate($arParameters, $HashKey, $HashIV, $arParameters['EncryptType']);
0 ignored issues
show
Unused Code introduced by
The call to ECPay_CheckMacValue::generate() has too many arguments starting with $arParameters['EncryptType'].

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...
547
548
        //生成表單,自動送出
549
        $szHtml = '<!DOCTYPE html>';
550
        $szHtml .= '<html>';
551
        $szHtml .= '<head>';
552
        $szHtml .= '<meta charset="utf-8">';
553
        $szHtml .= '</head>';
554
        $szHtml .= '<body>';
555
        $szHtml .= "<form id=\"__ecpayForm\" method=\"post\" target=\"{$target}\" action=\"{$ServiceURL}\">";
556
557
        foreach ($arParameters as $keys => $value) {
558
            $szHtml .= "<input type=\"hidden\" name=\"{$keys}\" value='{$value}' />";
559
        }
560
561
        $szHtml .= "<input type=\"hidden\" name=\"CheckMacValue\" value=\"{$szCheckMacValue}\" />";
562
        $szHtml .= '</form>';
563
        $szHtml .= '<script type="text/javascript">document.getElementById("__ecpayForm").submit();</script>';
564
        $szHtml .= '</body>';
565
        $szHtml .= '</html>';
566
567
        echo $szHtml;
568
        exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method CheckOut() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
569
    }
570
571 View Code Duplication
    public static function CheckOutString($paymentButton, $target = '_self', $arParameters = [], $arExtend = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
0 ignored issues
show
Duplication introduced by
This method 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...
572
    {
573
        $arParameters = self::process($arParameters, $arExtend);
574
        //產生檢查碼
575
        $szCheckMacValue = ECPay_CheckMacValue::generate($arParameters, $HashKey, $HashIV, $arParameters['EncryptType']);
0 ignored issues
show
Unused Code introduced by
The call to ECPay_CheckMacValue::generate() has too many arguments starting with $arParameters['EncryptType'].

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...
576
577
        $szHtml = '<!DOCTYPE html>';
578
        $szHtml .= '<html>';
579
        $szHtml .= '<head>';
580
        $szHtml .= '<meta charset="utf-8">';
581
        $szHtml .= '</head>';
582
        $szHtml .= '<body>';
583
        $szHtml .= "<form id=\"__ecpayForm\" method=\"post\" target=\"{$target}\" action=\"{$ServiceURL}\">";
584
585
        foreach ($arParameters as $keys => $value) {
586
            $szHtml .= "<input type=\"hidden\" name=\"{$keys}\" value='{$value}' />";
587
        }
588
589
        $szHtml .= "<input type=\"hidden\" name=\"CheckMacValue\" value=\"{$szCheckMacValue}\" />";
590
        $szHtml .= "<input type=\"submit\" id=\"__paymentButton\" value=\"{$paymentButton}\" />";
591
        $szHtml .= '</form>';
592
        $szHtml .= '</body>';
593
        $szHtml .= '</html>';
594
595
        return  $szHtml;
596
    }
597
598
    protected static function process($arParameters = [], $arExtend = [])
599
    {
600
        //宣告付款方式物件
601
        $PaymentMethod = 'ECPay_'.$arParameters['ChoosePayment'];
602
        self::$PaymentObj = new $PaymentMethod;
603
604
        //檢查參數
605
        $arParameters = self::$PaymentObj->check_string($arParameters);
606
607
        //檢查商品
608
        $arParameters = self::$PaymentObj->check_goods($arParameters);
609
610
        //檢查各付款方式的額外參數&電子發票參數
611
        $arExtend = self::$PaymentObj->check_extend_string($arExtend, $arParameters['InvoiceMark']);
612
613
        //過濾
614
        $arExtend = self::$PaymentObj->filter_string($arExtend, $arParameters['InvoiceMark']);
615
616
        //合併共同參數及延伸參數
617
        return array_merge($arParameters, $arExtend);
618
    }
619
}
620
621
class ECPay_CheckOutFeedback extends ECPay_Aio
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
622
{
623
    public static function CheckOut($arParameters = [], $HashKey = '', $HashIV = '')
624
    {
625
        // 變數宣告。
626
        $arErrors = [];
627
        $arFeedback = [];
628
        $szCheckMacValue = '';
0 ignored issues
show
Unused Code introduced by
$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...
629
        // 重新整理回傳參數。
630
        foreach ($arParameters as $keys => $value) {
631
            if ($keys != 'CheckMacValue') {
632
                if ($keys == 'PaymentType') {
633
                    $value = str_replace('_CVS', '', $value);
634
                    $value = str_replace('_BARCODE', '', $value);
635
                    $value = str_replace('_CreditCard', '', $value);
636
                }
637
                if ($keys == 'PeriodType') {
638
                    $value = str_replace('Y', 'Year', $value);
639
                    $value = str_replace('M', 'Month', $value);
640
                    $value = str_replace('D', 'Day', $value);
641
                }
642
                $arFeedback[$keys] = $value;
643
            }
644
        }
645
646
        $CheckMacValue = ECPay_CheckMacValue::generate($arParameters, $HashKey, $HashIV, 0);
0 ignored issues
show
Unused Code introduced by
The call to ECPay_CheckMacValue::generate() 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...
647
648
        if ($CheckMacValue != $arParameters['CheckMacValue']) {
649
            array_push($arErrors, 'CheckMacValue verify fail.');
650
        }
651
652
        if (count($arErrors) > 0) {
653
            throw new Exception(implode('- ', $arErrors));
654
        }
655
656
        return $arFeedback;
657
    }
658
}
659
660
class ECPay_QueryTradeInfo extends ECPay_Aio
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
661
{
662
    public static function CheckOut($arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
663
    {
664
        $arErrors = [];
665
        $arParameters['TimeStamp'] = time();
666
        $arFeedback = [];
667
        $arConfirmArgs = [];
668
        // 呼叫查詢。
669
        if (count($arErrors) == 0) {
670
            $arParameters['CheckMacValue'] = ECPay_CheckMacValue::generate($arParameters, $HashKey, $HashIV, 0);
0 ignored issues
show
Unused Code introduced by
The call to ECPay_CheckMacValue::generate() 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...
671
            // 送出查詢並取回結果。
672
            $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...
673
            $szResult = str_replace(' ', '%20', $szResult);
674
            $szResult = str_replace('+', '%2B', $szResult);
675
676
            // 轉結果為陣列。
677
            parse_str($szResult, $arParameters);
678
            // 重新整理回傳參數。
679
            foreach ($arParameters as $keys => $value) {
0 ignored issues
show
Bug introduced by
The expression $arParameters 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...
680
                if ($keys == 'CheckMacValue') {
681
                    $szCheckMacValue = $value;
682
                } else {
683
                    $arFeedback[$keys] = $value;
684
                    $arConfirmArgs[$keys] = $value;
685
                }
686
            }
687
688
            // 驗證檢查碼。
689
            if (count($arFeedback) > 0) {
690
                $szConfirmMacValue = ECPay_CheckMacValue::generate($arConfirmArgs, $HashKey, $HashIV, 0);
0 ignored issues
show
Unused Code introduced by
The call to ECPay_CheckMacValue::generate() 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...
691
                if ($szCheckMacValue != $szConfirmMacValue) {
0 ignored issues
show
Bug introduced by
The variable $szCheckMacValue does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
692
                    array_push($arErrors, 'CheckMacValue verify fail.');
693
                }
694
            }
695
        }
696
697
        if (count($arErrors) > 0) {
698
            throw new Exception(implode('- ', $arErrors));
699
        }
700
701
        return $arFeedback;
702
    }
703
}
704
705
class ECPay_QueryPeriodCreditCardTradeInfo extends ECPay_Aio
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
706
{
707
    public static function CheckOut($arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
708
    {
709
        $arErrors = [];
710
        $arParameters['TimeStamp'] = time();
711
        $arFeedback = [];
712
        $arConfirmArgs = [];
0 ignored issues
show
Unused Code introduced by
$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...
713
        // 呼叫查詢。
714
        if (count($arErrors) == 0) {
715
            $arParameters['CheckMacValue'] = ECPay_CheckMacValue::generate($arParameters, $HashKey, $HashIV, 0);
0 ignored issues
show
Unused Code introduced by
The call to ECPay_CheckMacValue::generate() 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...
716
            // 送出查詢並取回結果。
717
            $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...
718
            $szResult = str_replace(' ', '%20', $szResult);
719
            $szResult = str_replace('+', '%2B', $szResult);
720
721
            // 轉結果為陣列。
722
            $arParameters = json_decode($szResult, true);
723
            // 重新整理回傳參數。
724
            foreach ($arParameters as $keys => $value) {
725
                $arFeedback[$keys] = $value;
726
            }
727
        }
728
729
        if (count($arErrors) > 0) {
730
            throw new Exception(implode('- ', $arErrors));
731
        }
732
733
        return $arFeedback;
734
    }
735
}
736
737
class ECPay_DoAction extends ECPay_Aio
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
738
{
739
    public static function CheckOut($arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
740
    {
741
        // 變數宣告。
742
        $arErrors = [];
743
        $arFeedback = [];
744
745
        //產生驗證碼
746
        $szCheckMacValue = ECPay_CheckMacValue::generate($arParameters, $HashKey, $HashIV, 0);
0 ignored issues
show
Unused Code introduced by
The call to ECPay_CheckMacValue::generate() 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...
747
        $arParameters['CheckMacValue'] = $szCheckMacValue;
748
        // 送出查詢並取回結果。
749
        $szResult = self::ServerPost($arParameters, $ServiceURL);
750
        // 轉結果為陣列。
751
        parse_str($szResult, $arParameters);
752
        // 重新整理回傳參數。
753
        foreach ($arParameters as $keys => $value) {
0 ignored issues
show
Bug introduced by
The expression $arParameters 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...
754
            if ($keys == 'CheckMacValue') {
755
                $szCheckMacValue = $value;
0 ignored issues
show
Unused Code introduced by
$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...
756
            } else {
757
                $arFeedback[$keys] = $value;
758
            }
759
        }
760
761
        if (array_key_exists('RtnCode', $arFeedback) && $arFeedback['RtnCode'] != '1') {
762
            array_push($arErrors, vsprintf('#%s: %s', [$arFeedback['RtnCode'], $arFeedback['RtnMsg']]));
763
        }
764
765
        if (count($arErrors) > 0) {
766
            throw new Exception(implode('- ', $arErrors));
767
        }
768
769
        return $arFeedback;
770
    }
771
}
772
773
class ECPay_AioCapture extends ECPay_Aio
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
774
{
775
    public static function Capture($arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
776
    {
777
        $arErrors = [];
778
        $arFeedback = [];
779
780
        $szCheckMacValue = ECPay_CheckMacValue::generate($arParameters, $HashKey, $HashIV, 0);
0 ignored issues
show
Unused Code introduced by
The call to ECPay_CheckMacValue::generate() 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...
781
        $arParameters['CheckMacValue'] = $szCheckMacValue;
782
783
        // 送出查詢並取回結果。
784
        $szResult = self::ServerPost($arParameters, $ServiceURL);
785
786
        // 轉結果為陣列。
787
        parse_str($szResult, $arParameters);
788
789
        // 重新整理回傳參數。
790
        foreach ($arParameters as $keys => $value) {
0 ignored issues
show
Bug introduced by
The expression $arParameters 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...
791
            $arFeedback[$keys] = $value;
792
        }
793
794
        if (count($arErrors) > 0) {
795
            throw new Exception(implode('- ', $arErrors));
796
        }
797
798
        return $arFeedback;
799
    }
800
}
801
802
abstract class ECPay_Verification
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
803
{
804
    // 電子發票延伸參數。
805
    public $arInvoice = [
806
            'RelateNumber',
807
            'CustomerIdentifier',
808
            'CarrierType',
809
            'CustomerID',
810
            'Donation',
811
            'Print',
812
            'TaxType',
813
            'CustomerName',
814
            'CustomerAddr',
815
            'CustomerPhone',
816
            'CustomerEmail',
817
            'ClearanceMark',
818
            'CarrierNum',
819
            'LoveCode',
820
            'InvoiceRemark',
821
            'DelayDay',
822
            'InvoiceItemName',
823
            'InvoiceItemCount',
824
            'InvoiceItemWord',
825
            'InvoiceItemPrice',
826
            'InvoiceItemTaxType',
827
            'InvType',
828
        ];
829
830
    abstract public function check_goods($arParameters = []);
831
832
    abstract public function filter_string($arExtend = [], $InvoiceMark = '');
833
834
    abstract public function check_extend_string($arExtend = [], $InvoiceMark = '');
835
836
    //檢查共同參數
837
    public function check_string($arParameters = [])
838
    {
839
        $arErrors = [];
840
        if (strlen($arParameters['MerchantID']) == 0) {
841
            array_push($arErrors, 'MerchantID is required.');
842
        }
843
        if (strlen($arParameters['MerchantID']) > 10) {
844
            array_push($arErrors, 'MerchantID max langth as 10.');
845
        }
846
847
        if (strlen($arParameters['ReturnURL']) == 0) {
848
            array_push($arErrors, 'ReturnURL is required.');
849
        }
850
        if (strlen($arParameters['ClientBackURL']) > 200) {
851
            array_push($arErrors, 'ClientBackURL max langth as 200.');
852
        }
853
        if (strlen($arParameters['OrderResultURL']) > 200) {
854
            array_push($arErrors, 'OrderResultURL max langth as 200.');
855
        }
856
857
        if (strlen($arParameters['MerchantTradeNo']) == 0) {
858
            array_push($arErrors, 'MerchantTradeNo is required.');
859
        }
860
        if (strlen($arParameters['MerchantTradeNo']) > 20) {
861
            array_push($arErrors, 'MerchantTradeNo max langth as 20.');
862
        }
863
        if (strlen($arParameters['MerchantTradeDate']) == 0) {
864
            array_push($arErrors, 'MerchantTradeDate is required.');
865
        }
866
        if (strlen($arParameters['TotalAmount']) == 0) {
867
            array_push($arErrors, 'TotalAmount is required.');
868
        }
869
        if (strlen($arParameters['TradeDesc']) == 0) {
870
            array_push($arErrors, 'TradeDesc is required.');
871
        }
872
        if (strlen($arParameters['TradeDesc']) > 200) {
873
            array_push($arErrors, 'TradeDesc max langth as 200.');
874
        }
875
        if (strlen($arParameters['ChoosePayment']) == 0) {
876
            array_push($arErrors, 'ChoosePayment is required.');
877
        }
878
        if (strlen($arParameters['NeedExtraPaidInfo']) == 0) {
879
            array_push($arErrors, 'NeedExtraPaidInfo is required.');
880
        }
881
        if (count($arParameters['Items']) == 0) {
882
            array_push($arErrors, 'Items is required.');
883
        }
884
885
        // 檢查CheckMacValue加密方式
886
        if (strlen($arParameters['EncryptType']) > 1) {
887
            array_push($arErrors, 'EncryptType max langth as 1.');
888
        }
889
890
        if (count($arErrors) > 0) {
891
            throw new Exception(implode('<br>', $arErrors));
892
        }
893
    }
894
895
    //檢查電子發票參數
896
    public function check_invoiceString($arExtend = [])
897
    {
898
        $arErrors = [];
899
900
        // 廠商自訂編號RelateNumber(不可為空)
901 View Code Duplication
        if (! array_key_exists('RelateNumber', $arExtend)) {
0 ignored issues
show
Duplication introduced by
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...
902
            array_push($arErrors, 'RelateNumber is required.');
903
        } else {
904
            if (strlen($arExtend['RelateNumber']) > 30) {
905
                array_push($arErrors, 'RelateNumber max length as 30.');
906
            }
907
        }
908
909
        // 統一編號CustomerIdentifier(預設為空字串)
910 View Code Duplication
        if (! array_key_exists('CustomerIdentifier', $arExtend)) {
0 ignored issues
show
Duplication introduced by
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...
911
            $arExtend['CustomerIdentifier'] = '';
912
        } else {
913
            //統編長度只能為8
914
            if (strlen($arExtend['CustomerIdentifier']) != 8) {
915
                array_push($arErrors, 'CustomerIdentifier length should be 8.');
916
            }
917
        }
918
919
        // 載具類別CarrierType(預設為None)
920
        if (! array_key_exists('CarrierType', $arExtend)) {
921
            $arExtend['CarrierType'] = ECPay_CarrierType::None;
922 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
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...
923
            //有設定統一編號的話,載具參數必須是空字串
924
            if (strlen($arExtend['CustomerIdentifier']) > 0 && $arExtend['CarrierType'] != ECPay_CarrierType::None) {
925
                array_push($arErrors, 'CarrierType should be None.');
926
            }
927
        }
928
929
        // 客戶代號CustomerID(預設為空字串)
930
        if (! array_key_exists('CustomerID', $arExtend)) {
931
            $arExtend['CustomerID'] = '';
932 View Code Duplication
        } else {
0 ignored issues
show
Duplication introduced by
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...
933
            if ($arExtend['CarrierType'] == ECPay_CarrierType::Member && strlen($arExtend['CustomerID'] == 0)) {
934
                array_push($arErrors, 'CustomerID is required.');
935
            }
936
        }
937
        // 捐贈註記 Donation(預設為No)
938 View Code Duplication
        if (! array_key_exists('Donation', $arExtend)) {
0 ignored issues
show
Duplication introduced by
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...
939
            $arExtend['Donation'] = ECPay_Donation::No;
940
        } else {
941
            //若有帶統一編號,不可捐贈
942
            if (strlen($arExtend['CustomerIdentifier']) > 0 && $arExtend['Donation'] != ECPay_Donation::No) {
943
                array_push($arErrors, 'Donation should be No.');
944
            }
945
        }
946
947
        // 列印註記Print(預設為No)
948
        if (! array_key_exists('Print', $arExtend)) {
949
            $arExtend['Print'] = ECPay_PrintMark::No;
950
        } else {
951
            //捐贈註記為捐贈(Yes)時,請設定不列印(No)
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
952
            if ($arExtend['Donation'] == ECPay_Donation::Yes && $arExtend['Print'] != ECPay_PrintMark::No) {
953
                array_push($arErrors, 'Print should be No.');
954
            }
955
            // 統一編號不為空字串時,請設定列印(Yes)
956
            if (strlen($arExtend['CustomerIdentifier']) > 0 && $arExtend['Print'] != ECPay_PrintMark::Yes) {
957
                array_push($arErrors, 'Print should be Yes.');
958
            }
959
            // 載具類別為會員載具(Member)、買受人自然人憑證(Citizen)、買受人手機條碼(Cellphone)時,請設定不列印(No)
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
960
            $notPrint = [ECPay_CarrierType::Member, ECPay_CarrierType::Citizen, ECPay_CarrierType::Cellphone];
961
            if (in_array($arExtend['CarrierType'], $notPrint) and $arExtend['Print'] == ECPay_PrintMark::Yes) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
962
                array_push($arErrors, 'Print should be No.');
963
            }
964
        }
965
        // 客戶名稱CustomerName(UrlEncode, 預設為空字串)
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
966 View Code Duplication
        if (! array_key_exists('CustomerName', $arExtend)) {
0 ignored issues
show
Duplication introduced by
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...
967
            $arExtend['CustomerName'] = '';
968
        } else {
969
            if (mb_strlen($arExtend['CustomerName'], 'UTF-8') > 20) {
970
                array_push($arErrors, 'CustomerName max length as 20.');
971
            }
972
            // 列印註記為列印(Yes)時,此參數不可為空字串
973
            if ($arExtend['Print'] == ECPay_PrintMark::Yes && strlen($arExtend['CustomerName']) == 0) {
974
                array_push($arErrors, 'CustomerName is required.');
975
            }
976
        }
977
978
        // 客戶地址CustomerAddr(UrlEncode, 預設為空字串)
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
979 View Code Duplication
        if (! array_key_exists('CustomerAddr', $arExtend)) {
0 ignored issues
show
Duplication introduced by
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...
980
            $arExtend['CustomerAddr'] = '';
981
        } else {
982
            if (mb_strlen($arExtend['CustomerAddr'], 'UTF-8') > 200) {
983
                array_push($arErrors, 'CustomerAddr max length as 200.');
984
            }
985
            // 列印註記為列印(Yes)時,此參數不可為空字串
986
            if ($arExtend['Print'] == ECPay_PrintMark::Yes && strlen($arExtend['CustomerAddr']) == 0) {
987
                array_push($arErrors, 'CustomerAddr is required.');
988
            }
989
        }
990
        // 客戶電話CustomerPhone
991 View Code Duplication
        if (! array_key_exists('CustomerPhone', $arExtend)) {
0 ignored issues
show
Duplication introduced by
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...
992
            $arExtend['CustomerPhone'] = '';
993
        } else {
994
            if (strlen($arExtend['CustomerPhone']) > 20) {
995
                array_push($arErrors, 'CustomerPhone max length as 20.');
996
            }
997
        }
998
999
        // 客戶信箱CustomerEmail
1000 View Code Duplication
        if (! array_key_exists('CustomerEmail', $arExtend)) {
0 ignored issues
show
Duplication introduced by
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...
1001
            $arExtend['CustomerEmail'] = '';
1002
        } else {
1003
            if (strlen($arExtend['CustomerEmail']) > 200) {
1004
                array_push($arErrors, 'CustomerEmail max length as 200.');
1005
            }
1006
        }
1007
1008
        //(CustomerEmail與CustomerPhone擇一不可為空)
1009
        if (strlen($arExtend['CustomerPhone']) == 0 and strlen($arExtend['CustomerEmail']) == 0) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
1010
            array_push($arErrors, 'CustomerPhone or CustomerEmail is required.');
1011
        }
1012
1013
        //課稅類別 TaxType(不可為空)
1014
        if (strlen($arExtend['TaxType']) == 0) {
1015
            array_push($arErrors, 'TaxType is required.');
1016
        }
1017
1018
        //通關方式 ClearanceMark(預設為空字串)
1019
        if (! array_key_exists('ClearanceMark', $arExtend)) {
1020
            $arExtend['ClearanceMark'] = '';
1021
        } else {
1022
            //課稅類別為零稅率(Zero)時,ClearanceMark不可為空字串
1023
            if ($arExtend['TaxType'] == ECPay_TaxType::Zero && ($arExtend['ClearanceMark'] != ECPay_ClearanceMark::Yes || $arExtend['ClearanceMark'] != ECPay_ClearanceMark::No)) {
1024
                array_push($arErrors, 'ClearanceMark is required.');
1025
            }
1026
            if (strlen($arExtend['ClearanceMark']) > 0 && $arExtend['TaxType'] != ECPay_TaxType::Zero) {
1027
                array_push($arErrors, 'Please remove ClearanceMark.');
1028
            }
1029
        }
1030
1031
        // CarrierNum(預設為空字串)
1032
        if (! array_key_exists('CarrierNum', $arExtend)) {
1033
            $arExtend['CarrierNum'] = '';
1034
        } else {
1035
            switch ($arExtend['CarrierType']) {
1036
                // 載具類別為無載具(None)或會員載具(Member)時,請設定空字串
0 ignored issues
show
Unused Code Comprehensibility introduced by
40% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
1037
                case ECPay_CarrierType::None:
1038 View Code Duplication
                case ECPay_CarrierType::Member:
0 ignored issues
show
Duplication introduced by
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...
1039
                    if (strlen($arExtend['CarrierNum']) > 0) {
1040
                        array_push($arErrors, 'Please remove CarrierNum.');
1041
                    }
1042
                break;
1043
                // 載具類別為買受人自然人憑證(Citizen)時,請設定自然人憑證號碼,前2碼為大小寫英文,後14碼為數字
1044 View Code Duplication
                case ECPay_CarrierType::Citizen:
0 ignored issues
show
Duplication introduced by
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...
1045
                    if (! preg_match('/^[a-zA-Z]{2}\d{14}$/', $arExtend['CarrierNum'])) {
1046
                        array_push($arErrors, 'Invalid CarrierNum.');
1047
                    }
1048
                break;
1049
                // 載具類別為買受人手機條碼(Cellphone)時,請設定手機條碼,第1碼為「/」,後7碼為大小寫英文、數字、「+」、「-」或「.」
1050 View Code Duplication
                case ECPay_CarrierType::Cellphone:
0 ignored issues
show
Duplication introduced by
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...
1051
                    if (! preg_match('/^\/{1}[0-9a-zA-Z+-.]{7}$/', $arExtend['CarrierNum'])) {
1052
                        array_push($arErrors, 'Invalid CarrierNum.');
1053
                    }
1054
                break;
1055
1056
                default:
1057
                    array_push($arErrors, 'Please remove CarrierNum.');
1058
            }
1059
        }
1060
1061
        // 愛心碼 LoveCode(預設為空字串)
1062
        if (! array_key_exists('LoveCode', $arExtend)) {
1063
            $arExtend['LoveCode'] = '';
1064
        }
1065
        // 捐贈註記為捐贈(Yes)時,參數長度固定3~7碼,請設定全數字或第1碼大小寫「X」,後2~6碼全數字
1066 View Code Duplication
        if ($arExtend['Donation'] == ECPay_Donation::Yes) {
0 ignored issues
show
Duplication introduced by
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...
1067
            if (! preg_match('/^([xX]{1}[0-9]{2,6}|[0-9]{3,7})$/', $arExtend['LoveCode'])) {
1068
                array_push($arErrors, 'Invalid LoveCode.');
1069
            }
1070
        } else {
1071
            if (strlen($arExtend['LoveCode']) > 0) {
1072
                array_push($arErrors, 'Please remove LoveCode.');
1073
            }
1074
        }
1075
1076
        //備註 InvoiceRemark(UrlEncode, 預設為空字串)
1077
        if (! array_key_exists('InvoiceRemark', $arExtend)) {
1078
            $arExtend['InvoiceRemark'] = '';
1079
        }
1080
1081
        // 延遲天數 DelayDay(不可為空, 預設為0) 延遲天數,範圍0~15,設定為0時,付款完成後立即開立發票
1082
        if (! array_key_exists('DelayDay', $arExtend)) {
1083
            $arExtend['DelayDay'] = 0;
1084
        }
1085
        if ($arExtend['DelayDay'] < 0 or $arExtend['DelayDay'] > 15) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
1086
            array_push($arErrors, 'DelayDay should be 0 ~ 15.');
1087
        }
1088
1089
        // 字軌類別 InvType(不可為空)
1090
        if (! array_key_exists('InvType', $arExtend)) {
1091
            array_push($arErrors, 'InvType is required.');
1092
        }
1093
1094
        //商品相關整理
1095
        if (! array_key_exists('InvoiceItems', $arExtend)) {
1096
            array_push($arErrors, 'Invoice Goods information not found.');
1097
        } else {
1098
            $InvSptr = '|';
1099
            $tmpItemName = [];
1100
            $tmpItemCount = [];
1101
            $tmpItemWord = [];
1102
            $tmpItemPrice = [];
1103
            $tmpItemTaxType = [];
1104
            foreach ($arExtend['InvoiceItems'] as $tmpItemInfo) {
1105
                if (mb_strlen($tmpItemInfo['Name'], 'UTF-8') > 0) {
1106
                    array_push($tmpItemName, $tmpItemInfo['Name']);
1107
                }
1108
                if (strlen($tmpItemInfo['Count']) > 0) {
1109
                    array_push($tmpItemCount, $tmpItemInfo['Count']);
1110
                }
1111
                if (mb_strlen($tmpItemInfo['Word'], 'UTF-8') > 0) {
1112
                    array_push($tmpItemWord, $tmpItemInfo['Word']);
1113
                }
1114
                if (strlen($tmpItemInfo['Price']) > 0) {
1115
                    array_push($tmpItemPrice, $tmpItemInfo['Price']);
1116
                }
1117
                if (strlen($tmpItemInfo['TaxType']) > 0) {
1118
                    array_push($tmpItemTaxType, $tmpItemInfo['TaxType']);
1119
                }
1120
            }
1121
1122
            if ($arExtend['TaxType'] == ECPay_TaxType::Mix) {
1123
                if (in_array(ECPay_TaxType::Dutiable, $tmpItemTaxType) and in_array(ECPay_TaxType::Free, $tmpItemTaxType)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
1124
                    // Do nothing
1125
                } else {
1126
                    $tmpItemTaxType = [];
1127
                }
1128
            }
1129
            if ((count($tmpItemName) + count($tmpItemCount) + count($tmpItemWord) + count($tmpItemPrice) + count($tmpItemTaxType)) == (count($tmpItemName) * 5)) {
1130
                $arExtend['InvoiceItemName'] = implode($InvSptr, $tmpItemName);
1131
                $arExtend['InvoiceItemCount'] = implode($InvSptr, $tmpItemCount);
1132
                $arExtend['InvoiceItemWord'] = implode($InvSptr, $tmpItemWord);
1133
                $arExtend['InvoiceItemPrice'] = implode($InvSptr, $tmpItemPrice);
1134
                $arExtend['InvoiceItemTaxType'] = implode($InvSptr, $tmpItemTaxType);
1135
            }
1136
1137
            unset($arExtend['InvoiceItems']);
1138
        }
1139
1140
        $encode_fields = [
1141
                'CustomerName',
1142
                'CustomerAddr',
1143
                'CustomerEmail',
1144
                'InvoiceItemName',
1145
                'InvoiceItemWord',
1146
                'InvoiceRemark',
1147
            ];
1148
        foreach ($encode_fields as $tmp_field) {
1149
            $arExtend[$tmp_field] = urlencode($arExtend[$tmp_field]);
1150
        }
1151
1152
        if (count($arErrors) > 0) {
1153
            throw new Exception(implode('<br>', $arErrors));
1154
        }
1155
1156
        return $arExtend;
1157
    }
1158
}
1159
1160
/**
1161
 *  付款方式:超商代碼
1162
 */
1163 View Code Duplication
class ECPay_CVS extends ECPay_Verification
0 ignored issues
show
Duplication introduced by
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...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
1164
{
1165
    public $arPayMentExtend = [
1166
                            'Desc_1' => '',
1167
                            'Desc_2' => '',
1168
                            'Desc_3' => '',
1169
                            'Desc_4' => '',
1170
                            'PaymentInfoURL' => '',
1171
                            'ClientRedirectURL' => '',
1172
                            'StoreExpireDate' => '',
1173
                        ];
1174
1175
    //檢查共同參數
1176
    public function check_string($arParameters = [])
1177
    {
1178
        parent::check_string($arParameters);
1179
        if (! $arParameters['PlatformID']) {
1180
            unset($arParameters['PlatformID']);
1181
        }
1182
        unset($arParameters['IgnorePayment']);
1183
1184
        return $arParameters;
1185
    }
1186
1187
    //檢查CVS的延伸參數
1188
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1189
    {
1190
1191
        //沒設定參數的話,就給預設參數
1192
        foreach ($this->arPayMentExtend as $key => $value) {
1193
            if (! isset($arExtend[$key])) {
1194
                $arExtend[$key] = $value;
1195
            }
1196
        }
1197
1198
        //若有開發票,檢查一下發票參數
1199
        if ($InvoiceMark == 'Y') {
1200
            $arExtend = $this->check_invoiceString($arExtend);
1201
        }
1202
1203
        return $arExtend;
1204
    }
1205
1206
    //過濾多餘參數
1207
    public function filter_string($arExtend = [], $InvoiceMark = '')
1208
    {
1209
        $arPayMentExtend = ($InvoiceMark == '') ? array_keys($this->arPayMentExtend) : array_merge(array_keys($this->arPayMentExtend), $this->arInvoice);
1210
        foreach ($arExtend as $key => $value) {
1211
            if (! in_array($key, $arPayMentExtend)) {
1212
                unset($arExtend[$key]);
1213
            }
1214
        }
1215
1216
        return $arExtend;
1217
    }
1218
1219
    //檢查商品
1220
    public function check_goods($arParameters = [])
1221
    {
1222
        // 檢查產品名稱。
1223
        $szItemName = '';
1224
        $arErrors = [];
1225
        if (count($arParameters['Items']) > 0) {
1226
            foreach ($arParameters['Items'] as $keys => $value) {
1227
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1228
                if (! array_key_exists('ItemURL', $arParameters)) {
1229
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1230
                }
1231
            }
1232
1233
            if (strlen($szItemName) > 0) {
1234
                $szItemName = mb_substr($szItemName, 1, 200);
1235
                $arParameters['ItemName'] = $szItemName;
1236
            }
1237
        } else {
1238
            array_push($arErrors, 'Goods information not found.');
1239
        }
1240
1241
        if (count($arErrors) > 0) {
1242
            throw new Exception(implode('<br>', $arErrors));
1243
        }
1244
1245
        unset($arParameters['Items']);
1246
1247
        return $arParameters;
1248
    }
1249
}
1250
1251
/**
1252
 * 付款方式 : BARCODE.
1253
 */
1254 View Code Duplication
class ECPay_BARCODE extends ECPay_Verification
0 ignored issues
show
Duplication introduced by
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...
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
1255
{
1256
    public $arPayMentExtend = [
1257
                            'Desc_1' => '',
1258
                            'Desc_2' => '',
1259
                            'Desc_3' => '',
1260
                            'Desc_4' => '',
1261
                            'PaymentInfoURL' => '',
1262
                            'ClientRedirectURL' => '',
1263
                            'StoreExpireDate' => '',
1264
                        ];
1265
1266
    //檢查共同參數
1267
    public function check_string($arParameters = [])
1268
    {
1269
        parent::check_string($arParameters);
1270
        if (! $arParameters['PlatformID']) {
1271
            unset($arParameters['PlatformID']);
1272
        }
1273
        unset($arParameters['IgnorePayment']);
1274
1275
        return $arParameters;
1276
    }
1277
1278
    //檢查BARCODE的延伸參數
1279
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1280
    {
1281
1282
        //沒設定參數的話,就給預設參數
1283
        foreach ($this->arPayMentExtend as $key => $value) {
1284
            if (! isset($arExtend[$key])) {
1285
                $arExtend[$key] = $value;
1286
            }
1287
        }
1288
1289
        //若有開發票,檢查一下發票參數
1290
        if ($InvoiceMark == 'Y') {
1291
            $arExtend = $this->check_invoiceString($arExtend);
1292
        }
1293
1294
        return $arExtend;
1295
    }
1296
1297
    //過濾多餘參數
1298
    public function filter_string($arExtend = [], $InvoiceMark = '')
1299
    {
1300
        $arPayMentExtend = ($InvoiceMark == '') ? array_keys($this->arPayMentExtend) : array_merge(array_keys($this->arPayMentExtend), $this->arInvoice);
1301
        foreach ($arExtend as $key => $value) {
1302
            if (! in_array($key, $arPayMentExtend)) {
1303
                unset($arExtend[$key]);
1304
            }
1305
        }
1306
1307
        return $arExtend;
1308
    }
1309
1310
    //檢查商品
1311
    public function check_goods($arParameters = [])
1312
    {
1313
        // 檢查產品名稱。
1314
        $szItemName = '';
1315
        $arErrors = [];
1316
        if (count($arParameters['Items']) > 0) {
1317
            foreach ($arParameters['Items'] as $keys => $value) {
1318
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1319
                if (! array_key_exists('ItemURL', $arParameters)) {
1320
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1321
                }
1322
            }
1323
1324
            if (strlen($szItemName) > 0) {
1325
                $szItemName = mb_substr($szItemName, 1, 200);
1326
                $arParameters['ItemName'] = $szItemName;
1327
            }
1328
        } else {
1329
            array_push($arErrors, 'Goods information not found.');
1330
        }
1331
1332
        if (count($arErrors) > 0) {
1333
            throw new Exception(implode('<br>', $arErrors));
1334
        }
1335
1336
        unset($arParameters['Items']);
1337
1338
        return $arParameters;
1339
    }
1340
}
1341
1342
/**
1343
 *  付款方式 ATM.
1344
 */
1345
class ECPay_ATM extends ECPay_Verification
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
1346
{
1347
    public $arPayMentExtend = [
1348
                            'ExpireDate' => 3,
1349
                            'PaymentInfoURL' => '',
1350
                            'ClientRedirectURL' => '',
1351
                        ];
1352
1353
    //檢查共同參數
1354
    public function check_string($arParameters = [])
1355
    {
1356
        parent::check_string($arParameters);
1357
        if (! $arParameters['PlatformID']) {
1358
            unset($arParameters['PlatformID']);
1359
        }
1360
        unset($arParameters['IgnorePayment']);
1361
1362
        return $arParameters;
1363
    }
1364
1365
    //檢查ATM的延伸參數
1366
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1367
    {
1368
        //沒設定參數的話,就給預設參數
1369
        foreach ($this->arPayMentExtend as $key => $value) {
1370
            if (! isset($arExtend[$key])) {
1371
                $arExtend[$key] = $value;
1372
            }
1373
        }
1374
1375
        //若有開發票,檢查一下發票參數
1376
        if ($InvoiceMark == 'Y') {
1377
            $arExtend = $this->check_invoiceString($arExtend);
1378
        }
1379
1380
        return $arExtend;
1381
    }
1382
1383
    //過濾多餘參數
1384
    public function filter_string($arExtend = [], $InvoiceMark = '')
1385
    {
1386
        $arPayMentExtend = ($InvoiceMark == '') ? array_keys($this->arPayMentExtend) : array_merge(array_keys($this->arPayMentExtend), $this->arInvoice);
1387
        foreach ($arExtend as $key => $value) {
1388
            if (! in_array($key, $arPayMentExtend)) {
1389
                unset($arExtend[$key]);
1390
            }
1391
        }
1392
1393
        return $arExtend;
1394
    }
1395
1396
    //檢查商品
1397
    public function check_goods($arParameters = [])
1398
    {
1399
        // 檢查產品名稱。
1400
        $szItemName = '';
1401
        $arErrors = [];
1402
        if (count($arParameters['Items']) > 0) {
1403
            foreach ($arParameters['Items'] as $keys => $value) {
1404
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1405
                if (! array_key_exists('ItemURL', $arParameters)) {
1406
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1407
                }
1408
            }
1409
1410
            if (strlen($szItemName) > 0) {
1411
                $szItemName = mb_substr($szItemName, 1, 200);
1412
                $arParameters['ItemName'] = $szItemName;
1413
            }
1414
        } else {
1415
            array_push($arErrors, 'Goods information not found.');
1416
        }
1417
1418
        if (count($arErrors) > 0) {
1419
            throw new Exception(implode('<br>', $arErrors));
1420
        }
1421
1422
        unset($arParameters['Items']);
1423
1424
        return $arParameters;
1425
    }
1426
}
1427
1428
/**
1429
 *  付款方式 WebATM.
1430
 */
1431
class ECPay_WebATM extends ECPay_Verification
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
1432
{
1433
    public $arPayMentExtend = [];
1434
1435
    //檢查共同參數
1436
    public function check_string($arParameters = [])
1437
    {
1438
        parent::check_string($arParameters);
1439
        if (! $arParameters['PlatformID']) {
1440
            unset($arParameters['PlatformID']);
1441
        }
1442
        unset($arParameters['IgnorePayment']);
1443
1444
        return $arParameters;
1445
    }
1446
1447
    //檢查WebATM的延伸參數
1448
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1449
    {
1450
        //沒設定參數的話,就給預設參數
1451
        foreach ($this->arPayMentExtend as $key => $value) {
1452
            if (! isset($arExtend[$key])) {
1453
                $arExtend[$key] = $value;
1454
            }
1455
        }
1456
1457
        //若有開發票,檢查一下發票參數
1458
        if ($InvoiceMark == 'Y') {
1459
            $arExtend = $this->check_invoiceString($arExtend);
1460
        }
1461
1462
        return $arExtend;
1463
    }
1464
1465
    //過濾多餘參數
1466
    public function filter_string($arExtend = [], $InvoiceMark = '')
1467
    {
1468
        $arPayMentExtend = ($InvoiceMark == '') ? array_keys($this->arPayMentExtend) : array_merge(array_keys($this->arPayMentExtend), $this->arInvoice);
1469
        foreach ($arExtend as $key => $value) {
1470
            if (! in_array($key, $arPayMentExtend)) {
1471
                unset($arExtend[$key]);
1472
            }
1473
        }
1474
1475
        return $arExtend;
1476
    }
1477
1478
    //檢查商品
1479
    public function check_goods($arParameters = [])
1480
    {
1481
        // 檢查產品名稱。
1482
        $arErrors = [];
1483
        $szItemName = '';
1484
        if (count($arParameters['Items']) > 0) {
1485
            foreach ($arParameters['Items'] as $keys => $value) {
1486
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1487
                if (! array_key_exists('ItemURL', $arParameters)) {
1488
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1489
                }
1490
            }
1491
1492
            if (strlen($szItemName) > 0) {
1493
                $szItemName = mb_substr($szItemName, 1, 200);
1494
                $arParameters['ItemName'] = $szItemName;
1495
            }
1496
        } else {
1497
            array_push($arErrors, 'Goods information not found.');
1498
        }
1499
1500
        if (count($arErrors) > 0) {
1501
            throw new Exception(implode('<br>', $arErrors));
1502
        }
1503
1504
        unset($arParameters['Items']);
1505
1506
        return $arParameters;
1507
    }
1508
}
1509
1510
/**
1511
 * 付款方式 : 信用卡
1512
 */
1513
class ECPay_Credit extends ECPay_Verification
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
1514
{
1515
    public $arPayMentExtend = [
1516
                                    'CreditInstallment' => 0,
1517
                                    'InstallmentAmount' => 0,
1518
                                    'Redeem' => false,
1519
                                    'UnionPay' => false,
1520
                                    'Language' => '',
1521
                                    'PeriodAmount' => '',
1522
                                    'PeriodType' => '',
1523
                                    'Frequency' => '',
1524
                                    'ExecTimes' => '',
1525
                                    'PeriodReturnURL' => '',
1526
                                ];
1527
1528
    //檢查共同參數
1529
    public function check_string($arParameters = [])
1530
    {
1531
        parent::check_string($arParameters);
1532
        if (! $arParameters['PlatformID']) {
1533
            unset($arParameters['PlatformID']);
1534
        }
1535
        unset($arParameters['IgnorePayment']);
1536
1537
        return $arParameters;
1538
    }
1539
1540
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1541
    {
1542
        foreach ($this->arPayMentExtend as $key => $value) {
1543
            if (! isset($arExtend[$key])) {
1544
                $arExtend[$key] = $value;
1545
            }
1546
        }
1547
1548
        //若有開發票,檢查一下發票參數
1549
        if ($InvoiceMark == 'Y') {
1550
            $arExtend = $this->check_invoiceString($arExtend);
1551
        }
1552
1553
        return $arExtend;
1554
    }
1555
1556
    public function filter_string($arExtend = [], $InvoiceMark = '')
1557
    {
1558
        $arPayMentExtend = ($InvoiceMark == '') ? array_keys($this->arPayMentExtend) : array_merge(array_keys($this->arPayMentExtend), $this->arInvoice);
1559
        foreach ($arExtend as $key => $value) {
1560
            if (! in_array($key, $arPayMentExtend)) {
1561
                unset($arExtend[$key]);
1562
            }
1563
        }
1564
1565
        return $arExtend;
1566
    }
1567
1568
    //檢查商品
1569
    public function check_goods($arParameters = [])
1570
    {
1571
        // 檢查產品名稱。
1572
        $arErrors = [];
1573
        $szItemName = '';
1574
        if (count($arParameters['Items']) > 0) {
1575
            foreach ($arParameters['Items'] as $keys => $value) {
1576
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1577
                if (! array_key_exists('ItemURL', $arParameters)) {
1578
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1579
                }
1580
            }
1581
1582
            if (strlen($szItemName) > 0) {
1583
                $szItemName = mb_substr($szItemName, 1, 200);
1584
                $arParameters['ItemName'] = $szItemName;
1585
            }
1586
        } else {
1587
            array_push($arErrors, 'Goods information not found.');
1588
        }
1589
1590
        if (count($arErrors) > 0) {
1591
            throw new Exception(implode('<br>', $arErrors));
1592
        }
1593
1594
        unset($arParameters['Items']);
1595
1596
        return $arParameters;
1597
    }
1598
}
1599
1600
/**
1601
 *  付款方式:全功能.
1602
 */
1603
class ECPay_ALL extends ECPay_Verification
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
1604
{
1605
    public $arPayMentExtend = [];
1606
1607
    //檢查共同參數
1608
    public function check_string($arParameters = [])
1609
    {
1610
        parent::check_string($arParameters);
1611
        if (! $arParameters['PlatformID']) {
1612
            unset($arParameters['PlatformID']);
1613
        }
1614
1615
        return $arParameters;
1616
    }
1617
1618
    //檢查ALL的延伸參數
1619
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1620
    {
1621
        //若有開發票,檢查一下發票參數
1622
        if ($InvoiceMark == 'Y') {
1623
            $arExtend = $this->check_invoiceString($arExtend);
1624
        }
1625
1626
        return $arExtend;
1627
    }
1628
1629
    public function filter_string($arExtend = [], $InvoiceMark = '')
1630
    {
1631
        return $arExtend;
1632
    }
1633
1634
    //檢查商品
1635
    public function check_goods($arParameters = [])
1636
    {
1637
        // 檢查產品名稱。
1638
        $arErrors = [];
1639
1640
        $szItemName = '';
1641
        if (count($arParameters['Items']) > 0) {
1642
            foreach ($arParameters['Items'] as $keys => $value) {
1643
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1644
1645
                if (! array_key_exists('ItemURL', $arParameters)) {
1646
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1647
                }
1648
            }
1649
1650
            if (strlen($szItemName) > 0) {
1651
                $szItemName = mb_substr($szItemName, 1, 200);
1652
                $arParameters['ItemName'] = $szItemName;
1653
            }
1654
        } else {
1655
            array_push($arErrors, 'Goods information not found.');
1656
        }
1657
1658
        if (count($arErrors) > 0) {
1659
            throw new Exception(implode('<br>', $arErrors));
1660
        }
1661
        unset($arParameters['Items']);
1662
1663
        return $arParameters;
1664
    }
1665
}
1666
1667
/**
1668
 *  檢查碼
1669
 */
1670
class ECPay_CheckMacValue
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class should be in its own file to aid autoloaders.

Having each class in a dedicated file usually plays nice with PSR autoloaders and is therefore a well established practice. If you use other autoloaders, you might not want to follow this rule.

Loading history...
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
Comprehensibility Best Practice introduced by
The type ECPay_CheckMacValue has been defined more than once; this definition is ignored, only the first definition in sdk/ECPay.Logistics.Integration.php (L2371-2462) is considered.

This check looks for classes that have been defined more than once.

If you can, we would recommend to use standard object-oriented programming techniques. For example, to avoid multiple types, it might make sense to create a common interface, and then multiple, different implementations for that interface.

This also has the side-effect of providing you with better IDE auto-completion, static analysis and also better OPCode caching from PHP.

Loading history...
1671
{
1672
    public static function generate($arParameters = [], $HashKey = '', $HashIV = '', $encType = 0)
1673
    {
1674
        $sMacValue = '';
1675
1676
        if (isset($arParameters)) {
1677
            unset($arParameters['CheckMacValue']);
1678
            uksort($arParameters, ['ECPay_CheckMacValue', 'merchantSort']);
1679
1680
            // 組合字串
1681
            $sMacValue = 'HashKey='.$HashKey;
1682
            foreach ($arParameters as $key => $value) {
1683
                $sMacValue .= '&'.$key.'='.$value;
1684
            }
1685
1686
            $sMacValue .= '&HashIV='.$HashIV;
1687
1688
            // URL Encode編碼
1689
            $sMacValue = urlencode($sMacValue);
1690
1691
            // 轉成小寫
1692
            $sMacValue = strtolower($sMacValue);
1693
1694
            // 取代為與 dotNet 相符的字元
1695
            $sMacValue = str_replace('%2d', '-', $sMacValue);
1696
            $sMacValue = str_replace('%5f', '_', $sMacValue);
1697
            $sMacValue = str_replace('%2e', '.', $sMacValue);
1698
            $sMacValue = str_replace('%21', '!', $sMacValue);
1699
            $sMacValue = str_replace('%2a', '*', $sMacValue);
1700
            $sMacValue = str_replace('%28', '(', $sMacValue);
1701
            $sMacValue = str_replace('%29', ')', $sMacValue);
1702
1703
            // 編碼
1704
            switch ($encType) {
1705
                case ECPay_EncryptType::ENC_SHA256:
1706
                    // SHA256 編碼
1707
                    $sMacValue = hash('sha256', $sMacValue);
1708
                break;
1709
1710
                case ECPay_EncryptType::ENC_MD5:
1711
                default:
1712
                // MD5 編碼
1713
                    $sMacValue = md5($sMacValue);
1714
            }
1715
1716
            $sMacValue = strtoupper($sMacValue);
1717
        }
1718
1719
        return $sMacValue;
1720
    }
1721
1722
    /**
1723
     * 自訂排序使用.
1724
     */
1725
    private static function merchantSort($a, $b)
1726
    {
1727
        return strcasecmp($a, $b);
1728
    }
1729
}
1730