Completed
Push — master ( 7fd0a9...5689c0 )
by recca
02:13
created

ECPay_AioCapture::CheckOut()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 25
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 12
nc 4
nop 4
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_CarruerType
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
 *
407
 * @author charlie
408
 */
409
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...
410
{
411
    public $ServiceURL = 'ServiceURL';
412
    public $ServiceMethod = 'ServiceMethod';
413
    public $HashKey = 'HashKey';
414
    public $HashIV = 'HashIV';
415
    public $MerchantID = 'MerchantID';
416
    public $PaymentType = 'PaymentType';
417
    public $Send = 'Send';
418
    public $SendExtend = 'SendExtend';
419
    public $Query = 'Query';
420
    public $Action = 'Action';
421
    public $EncryptType = ECPay_EncryptType::ENC_MD5;
422
423
    public function __construct()
424
    {
425
        $this->PaymentType = 'aio';
426
        $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...
427
            'ReturnURL'         => '',
428
            'ClientBackURL'     => '',
429
            'OrderResultURL'    => '',
430
            'MerchantTradeNo'   => '',
431
            'MerchantTradeDate' => '',
432
            'PaymentType'       => 'aio',
433
            'TotalAmount'       => '',
434
            'TradeDesc'         => '',
435
            'ChoosePayment'     => ECPay_PaymentMethod::ALL,
436
            'Remark'            => '',
437
            'ChooseSubPayment'  => ECPay_PaymentMethodItem::None,
438
            'NeedExtraPaidInfo' => ECPay_ExtraPaymentInfo::No,
439
            'DeviceSource'      => '',
440
            'IgnorePayment'     => '',
441
            'PlatformID'        => '',
442
            'InvoiceMark'       => ECPay_InvoiceState::No,
443
            'Items'             => [],
444
            'EncryptType'       => ECPay_EncryptType::ENC_MD5,
445
        ];
446
447
        $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...
448
449
        $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...
450
            'MerchantTradeNo' => '', 'TimeStamp' => '',
451
        ];
452
        $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...
453
            'MerchantTradeNo' => '', 'TradeNo' => '', 'Action' => ECPay_ActionType::C, 'TotalAmount' => 0,
454
        ];
455
        $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...
456
    }
457
458
    //產生訂單
459
    public function CheckOut($target = '_self')
460
    {
461
        $arParameters = array_merge(['MerchantID' => $this->MerchantID], $this->Send);
462
        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...
463
    }
464
465
    //產生訂單html code
466
    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...
467
    {
468
        $arParameters = array_merge(['MerchantID' => $this->MerchantID], $this->Send);
469
470
        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...
471
    }
472
473
    //取得付款結果通知的方法
474
    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...
475
    {
476
        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...
477
    }
478
479
    //訂單查詢作業
480
    public function QueryTradeInfo()
481
    {
482
        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...
483
    }
484
485
    //信用卡定期定額訂單查詢的方法
486
    public function QueryPeriodCreditCardTradeInfo()
487
    {
488
        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...
489
    }
490
491
    //信用卡關帳/退刷/取消/放棄的方法
492
    public function DoAction()
493
    {
494
        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...
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
Bug introduced by
The method Capture() does not seem to exist on object<ECPay_AioCapture>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
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
    protected static function process($arParameters = [], $arExtend = [])
543
    {
544
        //宣告付款方式物件
545
        $PaymentMethod = 'ECPay_'.$arParameters['ChoosePayment'];
546
        self::$PaymentObj = new $PaymentMethod();
547
548
        //檢查參數
549
        $arParameters = self::$PaymentObj->check_string($arParameters);
550
551
        //檢查商品
552
        $arParameters = self::$PaymentObj->check_goods($arParameters);
553
554
        //檢查各付款方式的額外參數&電子發票參數
555
        $arExtend = self::$PaymentObj->check_extend_string($arExtend, $arParameters['InvoiceMark']);
556
557
        //過濾
558
        $arExtend = self::$PaymentObj->filter_string($arExtend, $arParameters['InvoiceMark']);
559
560
        //合併共同參數及延伸參數
561
        return array_merge($arParameters, $arExtend);
562
    }
563
564 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...
565
    {
566
        $arParameters = self::process($arParameters, $arExtend);
567
        //產生檢查碼
568
        $szCheckMacValue = ECPay_CheckMacValue::generate($arParameters, $HashKey, $HashIV, $arParameters['EncryptType']);
569
570
        //生成表單,自動送出
571
        $szHtml = '<!DOCTYPE html>';
572
        $szHtml .= '<html>';
573
        $szHtml .= '<head>';
574
        $szHtml .= '<meta charset="utf-8">';
575
        $szHtml .= '</head>';
576
        $szHtml .= '<body>';
577
        $szHtml .= "<form id=\"__ecpayForm\" method=\"post\" target=\"{$target}\" action=\"{$ServiceURL}\">";
578
579
        foreach ($arParameters as $keys => $value) {
580
            $szHtml .= "<input type=\"hidden\" name=\"{$keys}\" value='{$value}' />";
581
        }
582
583
        $szHtml .= "<input type=\"hidden\" name=\"CheckMacValue\" value=\"{$szCheckMacValue}\" />";
584
        $szHtml .= '</form>';
585
        $szHtml .= '<script type="text/javascript">document.getElementById("__ecpayForm").submit();</script>';
586
        $szHtml .= '</body>';
587
        $szHtml .= '</html>';
588
589
        echo $szHtml;
590
        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...
591
    }
592
593 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...
594
    {
595
        $arParameters = self::process($arParameters, $arExtend);
596
        //產生檢查碼
597
        $szCheckMacValue = ECPay_CheckMacValue::generate($arParameters, $HashKey, $HashIV, $arParameters['EncryptType']);
598
599
        $szHtml = '<!DOCTYPE html>';
600
        $szHtml .= '<html>';
601
        $szHtml .= '<head>';
602
        $szHtml .= '<meta charset="utf-8">';
603
        $szHtml .= '</head>';
604
        $szHtml .= '<body>';
605
        $szHtml .= "<form id=\"__ecpayForm\" method=\"post\" target=\"{$target}\" action=\"{$ServiceURL}\">";
606
607
        foreach ($arParameters as $keys => $value) {
608
            $szHtml .= "<input type=\"hidden\" name=\"{$keys}\" value='{$value}' />";
609
        }
610
611
        $szHtml .= "<input type=\"hidden\" name=\"CheckMacValue\" value=\"{$szCheckMacValue}\" />";
612
        $szHtml .= "<input type=\"submit\" id=\"__paymentButton\" value=\"{$paymentButton}\" />";
613
        $szHtml .= '</form>';
614
        $szHtml .= '</body>';
615
        $szHtml .= '</html>';
616
617
        return  $szHtml;
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);
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);
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);
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);
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);
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 CheckOut($arParameters = [], $HashKey = '', $HashIV = '', $ServiceURL = '')
776
    {
777
        $arErrors = [];
778
        $arFeedback = [];
779
780
        $szCheckMacValue = ECPay_CheckMacValue::generate($arParameters, $HashKey, $HashIV, 0);
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
    abstract public function check_goods($arParameters = []);
805
806
    abstract public function filter_string($arExtend = [], $InvoiceMark = '');
807
808
    abstract public function check_extend_string($arExtend = [], $InvoiceMark = '');
809
810
    // 電子發票延伸參數。
811
    public $arInvoice = [
812
            'RelateNumber',
813
            'CustomerIdentifier',
814
            'CarruerType',
815
            'CustomerID',
816
            'Donation',
817
            'Print',
818
            'TaxType',
819
            'CustomerName',
820
            'CustomerAddr',
821
            'CustomerPhone',
822
            'CustomerEmail',
823
            'ClearanceMark',
824
            'CarruerNum',
825
            'LoveCode',
826
            'InvoiceRemark',
827
            'DelayDay',
828
            'InvoiceItemName',
829
            'InvoiceItemCount',
830
            'InvoiceItemWord',
831
            'InvoiceItemPrice',
832
            'InvoiceItemTaxType',
833
            'InvType',
834
        ];
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 10.');
852
        }
853
        if (strlen($arParameters['OrderResultURL']) > 200) {
854
            array_push($arErrors, 'OrderResultURL max langth as 10.');
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
        // 載具類別CarruerType(預設為None)
920
        if (! array_key_exists('CarruerType', $arExtend)) {
921
            $arExtend['CarruerType'] = ECPay_CarruerType::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['CarruerType'] != ECPay_CarruerType::None) {
925
                array_push($arErrors, 'CarruerType 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['CarruerType'] == ECPay_CarruerType::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['PrintMark'] != ECPay_Donation::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_CarruerType::Member, ECPay_CarruerType::Citizen, ECPay_CarruerType::Cellphone];
961
            if (in_array($arExtend['CarruerType'], $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
        // CarruerNum(預設為空字串)
1032
        if (! array_key_exists('CarruerNum', $arExtend)) {
1033
            $arExtend['CarruerNum'] = '';
1034
        } else {
1035
            switch ($arExtend['CarruerType']) {
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_CarruerType::None:
1038 View Code Duplication
                case ECPay_CarruerType::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['CarruerNum']) > 0) {
1040
                        array_push($arErrors, 'Please remove CarruerNum.');
1041
                    }
1042
                break;
1043
                // 載具類別為買受人自然人憑證(Citizen)時,請設定自然人憑證號碼,前2碼為大小寫英文,後14碼為數字
1044 View Code Duplication
                case ECPay_CarruerType::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['CarruerNum'])) {
1046
                        array_push($arErrors, 'Invalid CarruerNum.');
1047
                    }
1048
                break;
1049
                // 載具類別為買受人手機條碼(Cellphone)時,請設定手機條碼,第1碼為「/」,後7碼為大小寫英文、數字、「+」、「-」或「.」
1050 View Code Duplication
                case ECPay_CarruerType::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['CarruerNum'])) {
1052
                        array_push($arErrors, 'Invalid CarruerNum.');
1053
                    }
1054
                break;
1055
1056
                default:
1057
                    array_push($arErrors, 'Please remove CarruerNum.');
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
        unset($arParameters['Items']);
1245
1246
        return $arParameters;
1247
    }
1248
}
1249
1250
/**
1251
 * 付款方式 : BARCODE.
1252
 */
1253 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...
1254
{
1255
    public $arPayMentExtend = [
1256
                            'Desc_1'           => '',
1257
                            'Desc_2'           => '',
1258
                            'Desc_3'           => '',
1259
                            'Desc_4'           => '',
1260
                            'PaymentInfoURL'   => '',
1261
                            'ClientRedirectURL' => '',
1262
                            'StoreExpireDate'  => '',
1263
                        ];
1264
1265
    //檢查共同參數
1266
    public function check_string($arParameters = [])
1267
    {
1268
        parent::check_string($arParameters);
1269
        if (! $arParameters['PlatformID']) {
1270
            unset($arParameters['PlatformID']);
1271
        }
1272
        unset($arParameters['IgnorePayment']);
1273
1274
        return $arParameters;
1275
    }
1276
1277
    //檢查BARCODE的延伸參數
1278
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1279
    {
1280
1281
        //沒設定參數的話,就給預設參數
1282
        foreach ($this->arPayMentExtend as $key => $value) {
1283
            if (! isset($arExtend[$key])) {
1284
                $arExtend[$key] = $value;
1285
            }
1286
        }
1287
1288
        //若有開發票,檢查一下發票參數
1289
        if ($InvoiceMark == 'Y') {
1290
            $arExtend = $this->check_invoiceString($arExtend);
1291
        }
1292
1293
        return $arExtend;
1294
    }
1295
1296
    //過濾多餘參數
1297
    public function filter_string($arExtend = [], $InvoiceMark = '')
1298
    {
1299
        $arPayMentExtend = ($InvoiceMark == '') ? array_keys($this->arPayMentExtend) : array_merge(array_keys($this->arPayMentExtend), $this->arInvoice);
1300
        foreach ($arExtend as $key => $value) {
1301
            if (! in_array($key, $arPayMentExtend)) {
1302
                unset($arExtend[$key]);
1303
            }
1304
        }
1305
1306
        return $arExtend;
1307
    }
1308
1309
        //檢查商品
1310
    public function check_goods($arParameters = [])
1311
    {
1312
        // 檢查產品名稱。
1313
        $szItemName = '';
1314
        $arErrors = [];
1315
        if (count($arParameters['Items']) > 0) {
1316
            foreach ($arParameters['Items'] as $keys => $value) {
1317
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1318
                if (! array_key_exists('ItemURL', $arParameters)) {
1319
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1320
                }
1321
            }
1322
1323
            if (strlen($szItemName) > 0) {
1324
                $szItemName = mb_substr($szItemName, 1, 200);
1325
                $arParameters['ItemName'] = $szItemName;
1326
            }
1327
        } else {
1328
            array_push($arErrors, 'Goods information not found.');
1329
        }
1330
1331
        if (count($arErrors) > 0) {
1332
            throw new Exception(implode('<br>', $arErrors));
1333
        }
1334
        unset($arParameters['Items']);
1335
1336
        return $arParameters;
1337
    }
1338
}
1339
1340
/**
1341
 *  付款方式 ATM.
1342
 */
1343
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...
1344
{
1345
    public $arPayMentExtend = [
1346
                            'ExpireDate'       => 3,
1347
                            'PaymentInfoURL'   => '',
1348
                            'ClientRedirectURL' => '',
1349
                        ];
1350
1351
    //檢查共同參數
1352
    public function check_string($arParameters = [])
1353
    {
1354
        parent::check_string($arParameters);
1355
        if (! $arParameters['PlatformID']) {
1356
            unset($arParameters['PlatformID']);
1357
        }
1358
        unset($arParameters['IgnorePayment']);
1359
1360
        return $arParameters;
1361
    }
1362
1363
    //檢查ATM的延伸參數
1364
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1365
    {
1366
        //沒設定參數的話,就給預設參數
1367
        foreach ($this->arPayMentExtend as $key => $value) {
1368
            if (! isset($arExtend[$key])) {
1369
                $arExtend[$key] = $value;
1370
            }
1371
        }
1372
1373
        //若有開發票,檢查一下發票參數
1374
        if ($InvoiceMark == 'Y') {
1375
            $arExtend = $this->check_invoiceString($arExtend);
1376
        }
1377
1378
        return $arExtend;
1379
    }
1380
1381
    //過濾多餘參數
1382
    public function filter_string($arExtend = [], $InvoiceMark = '')
1383
    {
1384
        $arPayMentExtend = ($InvoiceMark == '') ? array_keys($this->arPayMentExtend) : array_merge(array_keys($this->arPayMentExtend), $this->arInvoice);
1385
        foreach ($arExtend as $key => $value) {
1386
            if (! in_array($key, $arPayMentExtend)) {
1387
                unset($arExtend[$key]);
1388
            }
1389
        }
1390
1391
        return $arExtend;
1392
    }
1393
1394
    //檢查商品
1395
    public function check_goods($arParameters = [])
1396
    {
1397
        // 檢查產品名稱。
1398
        $szItemName = '';
1399
        $arErrors = [];
1400
        if (count($arParameters['Items']) > 0) {
1401
            foreach ($arParameters['Items'] as $keys => $value) {
1402
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1403
                if (! array_key_exists('ItemURL', $arParameters)) {
1404
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1405
                }
1406
            }
1407
1408
            if (strlen($szItemName) > 0) {
1409
                $szItemName = mb_substr($szItemName, 1, 200);
1410
                $arParameters['ItemName'] = $szItemName;
1411
            }
1412
        } else {
1413
            array_push($arErrors, 'Goods information not found.');
1414
        }
1415
1416
        if (count($arErrors) > 0) {
1417
            throw new Exception(implode('<br>', $arErrors));
1418
        }
1419
        unset($arParameters['Items']);
1420
1421
        return $arParameters;
1422
    }
1423
}
1424
1425
/**
1426
 *  付款方式 WebATM.
1427
 */
1428
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...
1429
{
1430
    public $arPayMentExtend = [];
1431
1432
    //檢查共同參數
1433
    public function check_string($arParameters = [])
1434
    {
1435
        parent::check_string($arParameters);
1436
        if (! $arParameters['PlatformID']) {
1437
            unset($arParameters['PlatformID']);
1438
        }
1439
        unset($arParameters['IgnorePayment']);
1440
1441
        return $arParameters;
1442
    }
1443
1444
    //檢查WebATM的延伸參數
1445
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1446
    {
1447
        //沒設定參數的話,就給預設參數
1448
        foreach ($this->arPayMentExtend as $key => $value) {
1449
            if (! isset($arExtend[$key])) {
1450
                $arExtend[$key] = $value;
1451
            }
1452
        }
1453
1454
        //若有開發票,檢查一下發票參數
1455
        if ($InvoiceMark == 'Y') {
1456
            $arExtend = $this->check_invoiceString($arExtend);
1457
        }
1458
1459
        return $arExtend;
1460
    }
1461
1462
    //過濾多餘參數
1463
    public function filter_string($arExtend = [], $InvoiceMark = '')
1464
    {
1465
        $arPayMentExtend = ($InvoiceMark == '') ? array_keys($this->arPayMentExtend) : array_merge(array_keys($this->arPayMentExtend), $this->arInvoice);
1466
        foreach ($arExtend as $key => $value) {
1467
            if (! in_array($key, $arPayMentExtend)) {
1468
                unset($arExtend[$key]);
1469
            }
1470
        }
1471
1472
        return $arExtend;
1473
    }
1474
1475
    //檢查商品
1476
    public function check_goods($arParameters = [])
1477
    {
1478
        // 檢查產品名稱。
1479
        $arErrors = [];
1480
        $szItemName = '';
1481
        if (count($arParameters['Items']) > 0) {
1482
            foreach ($arParameters['Items'] as $keys => $value) {
1483
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1484
                if (! array_key_exists('ItemURL', $arParameters)) {
1485
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1486
                }
1487
            }
1488
1489
            if (strlen($szItemName) > 0) {
1490
                $szItemName = mb_substr($szItemName, 1, 200);
1491
                $arParameters['ItemName'] = $szItemName;
1492
            }
1493
        } else {
1494
            array_push($arErrors, 'Goods information not found.');
1495
        }
1496
1497
        if (count($arErrors) > 0) {
1498
            throw new Exception(implode('<br>', $arErrors));
1499
        }
1500
        unset($arParameters['Items']);
1501
1502
        return $arParameters;
1503
    }
1504
}
1505
1506
/**
1507
 * 付款方式 : 信用卡
1508
 */
1509
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...
1510
{
1511
    public $arPayMentExtend = [
1512
                                    'CreditInstallment' => 0,
1513
                                    'InstallmentAmount' => 0,
1514
                                    'Redeem'            => false,
1515
                                    'UnionPay'          => false,
1516
                                    'Language'          => '',
1517
                                    'PeriodAmount'      => '',
1518
                                    'PeriodType'        => '',
1519
                                    'Frequency'         => '',
1520
                                    'ExecTimes'         => '',
1521
                                    'PeriodReturnURL'   => '',
1522
                                ];
1523
1524
    //檢查共同參數
1525
    public function check_string($arParameters = [])
1526
    {
1527
        parent::check_string($arParameters);
1528
        if (! $arParameters['PlatformID']) {
1529
            unset($arParameters['PlatformID']);
1530
        }
1531
        unset($arParameters['IgnorePayment']);
1532
1533
        return $arParameters;
1534
    }
1535
1536
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1537
    {
1538
        foreach ($this->arPayMentExtend as $key => $value) {
1539
            if (! isset($arExtend[$key])) {
1540
                $arExtend[$key] = $value;
1541
            }
1542
        }
1543
1544
        //若有開發票,檢查一下發票參數
1545
        if ($InvoiceMark == 'Y') {
1546
            $arExtend = $this->check_invoiceString($arExtend);
1547
        }
1548
1549
        return $arExtend;
1550
    }
1551
1552
    public function filter_string($arExtend = [], $InvoiceMark = '')
1553
    {
1554
        $arPayMentExtend = ($InvoiceMark == '') ? array_keys($this->arPayMentExtend) : array_merge(array_keys($this->arPayMentExtend), $this->arInvoice);
1555
        foreach ($arExtend as $key => $value) {
1556
            if (! in_array($key, $arPayMentExtend)) {
1557
                unset($arExtend[$key]);
1558
            }
1559
        }
1560
1561
        return $arExtend;
1562
    }
1563
1564
    //檢查商品
1565
    public function check_goods($arParameters = [])
1566
    {
1567
        // 檢查產品名稱。
1568
        $arErrors = [];
1569
        $szItemName = '';
1570
        if (count($arParameters['Items']) > 0) {
1571
            foreach ($arParameters['Items'] as $keys => $value) {
1572
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1573
                if (! array_key_exists('ItemURL', $arParameters)) {
1574
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1575
                }
1576
            }
1577
1578
            if (strlen($szItemName) > 0) {
1579
                $szItemName = mb_substr($szItemName, 1, 200);
1580
                $arParameters['ItemName'] = $szItemName;
1581
            }
1582
        } else {
1583
            array_push($arErrors, 'Goods information not found.');
1584
        }
1585
1586
        if (count($arErrors) > 0) {
1587
            throw new Exception(implode('<br>', $arErrors));
1588
        }
1589
        unset($arParameters['Items']);
1590
1591
        return $arParameters;
1592
    }
1593
}
1594
1595
/**
1596
 *  付款方式:全功能.
1597
 */
1598
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...
1599
{
1600
    public $arPayMentExtend = [];
1601
1602
    //檢查共同參數
1603
    public function check_string($arParameters = [])
1604
    {
1605
        parent::check_string($arParameters);
1606
        if (! $arParameters['PlatformID']) {
1607
            unset($arParameters['PlatformID']);
1608
        }
1609
1610
        return $arParameters;
1611
    }
1612
1613
    //檢查ALL的延伸參數
1614
    public function check_extend_string($arExtend = [], $InvoiceMark = '')
1615
    {
1616
        //若有開發票,檢查一下發票參數
1617
        if ($InvoiceMark == 'Y') {
1618
            $arExtend = $this->check_invoiceString($arExtend);
1619
        }
1620
1621
        return $arExtend;
1622
    }
1623
1624
    public function filter_string($arExtend = [], $InvoiceMark = '')
1625
    {
1626
        return $arExtend;
1627
    }
1628
1629
    //檢查商品
1630
    public function check_goods($arParameters = [])
1631
    {
1632
        // 檢查產品名稱。
1633
        $arErrors = [];
1634
1635
        $szItemName = '';
1636
        if (count($arParameters['Items']) > 0) {
1637
            foreach ($arParameters['Items'] as $keys => $value) {
1638
                $szItemName .= vsprintf('#%s %d %s x %u', $arParameters['Items'][$keys]);
1639
1640
                if (! array_key_exists('ItemURL', $arParameters)) {
1641
                    $arParameters['ItemURL'] = $arParameters['Items'][$keys]['URL'];
1642
                }
1643
            }
1644
1645
            if (strlen($szItemName) > 0) {
1646
                $szItemName = mb_substr($szItemName, 1, 200);
1647
                $arParameters['ItemName'] = $szItemName;
1648
            }
1649
        } else {
1650
            array_push($arErrors, 'Goods information not found.');
1651
        }
1652
1653
        if (count($arErrors) > 0) {
1654
            throw new Exception(implode('<br>', $arErrors));
1655
        }
1656
        unset($arParameters['Items']);
1657
1658
        return $arParameters;
1659
    }
1660
}
1661
1662
/**
1663
 *  檢查碼
1664
 */
1665
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...
1666
{
1667
    public static function generate($arParameters = [], $HashKey = '', $HashIV = '', $encType = 0)
1668
    {
1669
        $sMacValue = '';
1670
1671
        if (isset($arParameters)) {
1672
            unset($arParameters['CheckMacValue']);
1673
            uksort($arParameters, ['ECPay_CheckMacValue', 'merchantSort']);
1674
1675
            // 組合字串
1676
            $sMacValue = 'HashKey='.$HashKey;
1677
            foreach ($arParameters as $key => $value) {
1678
                $sMacValue .= '&'.$key.'='.$value;
1679
            }
1680
1681
            $sMacValue .= '&HashIV='.$HashIV;
1682
1683
            // URL Encode編碼
1684
            $sMacValue = urlencode($sMacValue);
1685
1686
            // 轉成小寫
1687
            $sMacValue = strtolower($sMacValue);
1688
1689
            // 取代為與 dotNet 相符的字元
1690
            $sMacValue = str_replace('%2d', '-', $sMacValue);
1691
            $sMacValue = str_replace('%5f', '_', $sMacValue);
1692
            $sMacValue = str_replace('%2e', '.', $sMacValue);
1693
            $sMacValue = str_replace('%21', '!', $sMacValue);
1694
            $sMacValue = str_replace('%2a', '*', $sMacValue);
1695
            $sMacValue = str_replace('%28', '(', $sMacValue);
1696
            $sMacValue = str_replace('%29', ')', $sMacValue);
1697
1698
            // 編碼
1699
            switch ($encType) {
1700
                case ECPay_EncryptType::ENC_SHA256:
1701
                    // SHA256 編碼
1702
                    $sMacValue = hash('sha256', $sMacValue);
1703
                break;
1704
1705
                case ECPay_EncryptType::ENC_MD5:
1706
                default:
1707
                // MD5 編碼
1708
                    $sMacValue = md5($sMacValue);
1709
            }
1710
1711
            $sMacValue = strtoupper($sMacValue);
1712
        }
1713
1714
        return $sMacValue;
1715
    }
1716
1717
    /**
1718
     * 自訂排序使用.
1719
     */
1720
    private static function merchantSort($a, $b)
1721
    {
1722
        return strcasecmp($a, $b);
1723
    }
1724
}
1725