JeniusHttp::paymentRequest()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 50
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 31
c 1
b 0
f 0
dl 0
loc 50
rs 9.424
cc 1
nc 1
nop 8

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Jenius;
4
5
use Carbon\Carbon;
6
use Unirest\Request;
7
use Unirest\Request\Body;
8
use Unirest\Response;
9
10
class JeniusHttp
11
{
12
    /**
13
     * Default Timezone.
14
     *
15
     * @var string
16
     */
17
    private static $timezone = 'Asia/Jakarta';
18
19
    /**
20
     * Default Jenius Port.
21
     *
22
     * @var int
23
     */
24
    private static $port = 443;
25
26
    /**
27
     * Default Jenius Host.
28
     *
29
     * @var string
30
     */
31
    private static $hostName = 'apidev.btpn.com';
32
33
    /**
34
     * Default Jenius Scheme.
35
     *
36
     * @var string
37
     */
38
    private static $scheme = 'https';
39
40
    /**
41
     * Default Jenius Segment.
42
     *
43
     * @var string
44
     */
45
    private static $segment = 'pay';
46
47
    /**
48
     * Timeout curl.
49
     *
50
     * @var int
51
     */
52
    private static $timeOut = 60;
53
54
    /**
55
     * Default Curl Options.
56
     *
57
     * @var int
58
     */
59
    private static $curlOptions = array(
60
        CURLOPT_SSL_VERIFYHOST => 0,
61
        CURLOPT_SSLVERSION => 6,
62
        CURLOPT_SSL_VERIFYPEER => false,
63
        CURLOPT_TIMEOUT => 60
64
    );
65
66
    /**
67
     * Default Jenius Settings.
68
     *
69
     * @var array
70
     */
71
    protected $settings = array(
72
        'x_channel_id' => '',
73
        'client_id' => '',
74
        'client_secret' => '',
75
        'api_key' => '',
76
        'secret_key' => '',
77
        'curl_options' => array(),
78
        // Backward compatible
79
        'host' => 'apidev.btpn.com',
80
        'scheme' => 'https',
81
        'segment' => 'pay',
82
        'timeout' => 60,
83
        'port' => 443,
84
        // New Options
85
        'options' => array(
86
            'host' => 'apidev.btpn.com',
87
            'scheme' => 'https',
88
            'segment' => 'pay',
89
            'timeout' => 60,
90
            'port' => 443
91
        )
92
    );
93
94
    /**
95
     * Default Constructor.
96
     *
97
     * @param string $x_channel_id
98
     * @param string $client_id
99
     * @param string $client_secret
100
     * @param string $api_key
101
     * @param string $secret_key
102
     * @param array $options
103
     */
104
    public function __construct($x_channel_id, $client_id, $client_secret, $api_key, $secret_key, array $options = [])
105
    {
106
        // Required parameters.
107
        $this->settings['x-channel-id'] = $x_channel_id;
108
        $this->settings['client_id'] = $client_id;
109
        $this->settings['client_secret'] = $client_secret;
110
        $this->settings['api_key'] = $api_key;
111
        $this->settings['secret_key'] = $secret_key;
112
        $this->settings['host'] =
113
            preg_replace('/http[s]?\:\/\//', '', $this->settings['host'], 1);
114
115
        foreach ($options as $key => $value) {
116
            if (isset($this->settings[$key])) {
117
                $this->settings[$key] = $value;
118
            }
119
        }
120
121
        // Setup optional scheme, if scheme is empty
122
        if (isset($options['scheme'])) {
123
            $this->settings['scheme'] = $options['scheme'];
124
            $this->settings['options']['scheme'] = $options['scheme'];
125
        } else {
126
            $this->settings['scheme'] = self::getScheme();
127
            $this->settings['options']['scheme'] = self::getScheme();
128
        }
129
130
        // Setup optional host, if host is empty
131
        if (isset($options['host'])) {
132
            $this->settings['host'] = $options['host'];
133
            $this->settings['options']['host'] = $options['host'];
134
        } else {
135
            $this->settings['host'] = self::getHostName();
136
            $this->settings['options']['host'] = self::getHostName();
137
        }
138
139
        // Setup optional segment, if segment is empty
140
        if (isset($options['segment'])) {
141
            $this->settings['segment'] = $options['segment'];
142
            $this->settings['options']['segment'] = $options['segment'];
143
        } else {
144
            $this->settings['segment'] = self::getSegment();
145
            $this->settings['options']['segment'] = self::getSegment();
146
        }
147
148
        // Setup optional port, if port is empty
149
        if (isset($options['port'])) {
150
            $this->settings['port'] = $options['port'];
151
            $this->settings['options']['port'] = $options['port'];
152
        } else {
153
            $this->settings['port'] = self::getPort();
154
            $this->settings['options']['port'] = self::getPort();
155
        }
156
157
        // Setup optional timeout, if timeout is empty
158
        if (isset($options['timeout'])) {
159
            $this->settings['timeout'] = $options['timeout'];
160
            $this->settings['options']['timeout'] = $options['timeout'];
161
        } else {
162
            $this->settings['timeout'] = self::getTimeOut();
163
            $this->settings['options']['timeout'] = self::getTimeOut();
164
        }
165
166
        // Set Default Curl Options.
167
        Request::curlOpts(self::$curlOptions);
0 ignored issues
show
Bug introduced by
self::curlOptions of type integer is incompatible with the type array expected by parameter $options of Unirest\Request::curlOpts(). ( Ignorable by Annotation )

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

167
        Request::curlOpts(/** @scrutinizer ignore-type */ self::$curlOptions);
Loading history...
168
169
        // Set custom curl options
170
        if (!empty($this->settings['curl_options'])) {
171
            $data = self::mergeCurlOptions(self::$curlOptions, $this->settings['curl_options']);
0 ignored issues
show
Bug introduced by
self::curlOptions of type integer is incompatible with the type array expected by parameter $existing_options of Jenius\JeniusHttp::mergeCurlOptions(). ( Ignorable by Annotation )

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

171
            $data = self::mergeCurlOptions(/** @scrutinizer ignore-type */ self::$curlOptions, $this->settings['curl_options']);
Loading history...
172
            Request::curlOpts($data);
173
        }
174
    }
175
176
    /**
177
     * Get Settings
178
     *
179
     * @return array
180
     */
181
    public function getSettings()
182
    {
183
        return $this->settings;
184
    }
185
186
    /**
187
     * Build the ddn domain.
188
     * output = 'https://apidev.btpn.com:443'
189
     * scheme = http(s)
190
     * host = apidev.btpn.com
191
     * port = 80 ? 443
192
     *
193
     * @return string
194
     */
195
    private function ddnDomain()
196
    {
197
        return $this->settings['scheme'] . '://' . $this->settings['host'] . ':' . $this->settings['port'] . '/';
198
    }
199
200
    /**
201
     * Get Token
202
     *
203
     * @return Response
204
     */
205
    public function httpAuth()
206
    {
207
        $client_id = $this->settings['client_id'];
208
        $client_secret = $this->settings['client_secret'];
209
210
        $headerToken = base64_encode("$client_id:$client_secret");
211
212
        $headers = array(
213
            'Content-Type' => 'application/x-www-form-urlencoded',
214
            'Accept' => 'application/json',
215
            'Authorization' => "Basic $headerToken"
216
        );
217
218
        $request_path = "oauth/token";
219
        $domain = $this->ddnDomain();
220
        $full_url = $domain . $request_path;
221
222
        $data = array('grant_type' => 'client_credentials');
223
        $body = Body::form($data);
224
        $response = Request::post($full_url, $headers, $body);
225
226
        return $response;
227
    }
228
229
    /**
230
     * Create payment request
231
     *
232
     * @param string $oauth_token
233
     * @param int $amount
234
     * @param $cashtag
235
     * @param $promoCode
236
     * @param $urlCallback
237
     * @param $purchageDesc
238
     * @param $createdAt
239
     * @param $referenceNo
240
     * @return Response
241
     */
242
    public function paymentRequest(
243
        $oauth_token,
244
        $amount,
245
        $cashtag,
246
        $promoCode,
247
        $urlCallback,
248
        $purchageDesc,
249
        $createdAt,
250
        $referenceNo
251
    ) {
252
        $uriSign = "POST:/" . $this->settings['segment'] . "/payrequest";
253
        $apiKey = $this->settings['api_key'];
254
        $apiSecret = $this->settings['secret_key'];
255
256
        $btpnTimestamp = self::generateBtpnTimestamp();
257
        $btpnOriginalTimestamp = self::generateOriginalTimestamp($createdAt);
258
259
        $headers = array();
260
        $headers['Accept'] = 'application/json';
261
        $headers['Content-Type'] = 'application/json';
262
        $headers['Authorization'] = "Bearer $oauth_token";
263
        $headers['BTPN-ApiKey'] = $apiKey;
264
        $headers['BTPN-Timestamp'] = $btpnTimestamp;
265
        $headers['X-Channel-Id'] = $this->settings['x-channel-id'];
266
        $headers['X-Node'] = 'Jenius Pay';
267
        $headers['X-Transmission-Date-Time'] = $btpnTimestamp;
268
        $headers['X-Original-Transmission-Date-Time'] = $btpnOriginalTimestamp;
269
        $headers['X-Reference-No'] = $referenceNo;
270
271
        $request_path = $this->settings['segment'] . "/payrequest";
272
        $domain = $this->ddnDomain();
273
        $full_url = $domain . $request_path;
274
275
        $bodyData = array();
276
        $bodyData['txn_amount'] = $amount;
277
        $bodyData['cashtag'] = $cashtag;
278
        $bodyData['promo_code'] = $promoCode;
279
        $bodyData['url_callback'] = $urlCallback;
280
        $bodyData['purchase_desc'] = $purchageDesc;
281
282
        $authSignature = self::generateSign($uriSign, $apiKey, $apiSecret, $btpnTimestamp, $bodyData);
283
284
        $headers['BTPN-Signature'] = $authSignature;
285
286
        $encoderData = json_encode($bodyData, JSON_UNESCAPED_SLASHES);
287
288
        $body = Body::form($encoderData);
289
        $response = Request::post($full_url, $headers, $body);
290
291
        return $response;
292
    }
293
294
    /**
295
     * Get payment status
296
     *
297
     * @param string $oauth_token
298
     * @param $referenceNo
299
     * @param $createdAt
300
     * @return Response
301
     */
302
    public function paymentStatus(
303
        $oauth_token,
304
        $referenceNo,
305
        $createdAt
306
    ) {
307
        $uriSign = "GET:/" . $this->settings['segment'] . "/paystatus";
308
        $apiKey = $this->settings['api_key'];
309
        $apiSecret = $this->settings['secret_key'];
310
311
        $btpnTimestamp = self::generateBtpnTimestamp();
312
        $btpnOriginalTimestamp = self::generateOriginalTimestamp($createdAt);
313
314
        $headers = array();
315
        $headers['Accept'] = 'application/json';
316
        $headers['Content-Type'] = 'application/json';
317
        $headers['Authorization'] = "Bearer $oauth_token";
318
        $headers['BTPN-ApiKey'] = $apiKey;
319
        $headers['BTPN-Timestamp'] = $btpnTimestamp;
320
        $headers['X-Channel-Id'] = $this->settings['x-channel-id'];
321
        $headers['X-Node'] = 'Jenius Pay';
322
        $headers['X-Transmission-Date-Time'] = $btpnTimestamp;
323
        $headers['X-Original-Transmission-Date-Time'] = $btpnOriginalTimestamp;
324
        $headers['X-Reference-No'] = $referenceNo;
325
326
        $request_path = $this->settings['segment'] . "/paystatus";
327
        $domain = $this->ddnDomain();
328
        $full_url = $domain . $request_path;
329
330
        $authSignature = self::generateSign($uriSign, $apiKey, $apiSecret, $btpnTimestamp, []);
331
332
        $headers['BTPN-Signature'] = $authSignature;
333
334
        $response = Request::get($full_url, $headers, null);
335
336
        return $response;
337
    }
338
339
    /**
340
     * Create payment refund
341
     *
342
     * @param string $oauth_token
343
     * @param $approvalCode
344
     * @param $referenceNo
345
     * @param $amount
346
     * @param $createdAt
347
     * @return Response
348
     */
349
    public function paymentRefund(
350
        $oauth_token,
351
        $approvalCode,
352
        $referenceNo,
353
        $amount,
354
        $createdAt
355
    ) {
356
        $uriSign = "DELETE:/" . $this->settings['segment'] . "/payrefund?approval=" . $approvalCode;
357
        $apiKey = $this->settings['api_key'];
358
        $apiSecret = $this->settings['secret_key'];
359
360
        $btpnTimestamp = self::generateBtpnTimestamp();
361
        $btpnOriginalTimestamp = self::generateOriginalTimestamp($createdAt);
362
363
        $headers = array();
364
        $headers['Accept'] = 'application/json';
365
        $headers['Content-Type'] = 'application/json';
366
        $headers['Authorization'] = "Bearer $oauth_token";
367
        $headers['BTPN-ApiKey'] = $apiKey;
368
        $headers['BTPN-Timestamp'] = $btpnTimestamp;
369
        $headers['X-Channel-Id'] = $this->settings['x-channel-id'];
370
        $headers['X-Node'] = 'Jenius Pay';
371
        $headers['X-Transmission-Date-Time'] = $btpnTimestamp;
372
        $headers['X-Original-Transmission-Date-Time'] = $btpnOriginalTimestamp;
373
        $headers['X-Reference-No'] = $referenceNo;
374
        $headers['X-Amount'] = $amount;
375
376
377
        $request_path = $this->settings['segment'] . "/payrefund?approval=" . $approvalCode;
378
        $domain = $this->ddnDomain();
379
        $full_url = $domain . $request_path;
380
381
        $authSignature = self::generateSign($uriSign, $apiKey, $apiSecret, $btpnTimestamp, []);
382
383
        $headers['BTPN-Signature'] = $authSignature;
384
385
        $response = Request::delete($full_url, $headers, null);
386
387
        return $response;
388
    }
389
390
    /**
391
     * Generate Signature.
392
     *
393
     * @param string $url Url yang akan disign.
394
     * @param $apiKey
395
     * @param $apiSecret
396
     * @param $btpnTimestamp
397
     * @param array|mixed $bodyToHash array Body yang akan dikirimkan ke Server Jenius.
398
     *
399
     * @return string
400
     */
401
    public static function generateSign($url, $apiKey, $apiSecret, $btpnTimestamp, $bodyToHash = [])
402
    {
403
        if (!empty($bodyToHash)) {
404
            $encoderData = json_encode($bodyToHash, JSON_UNESCAPED_SLASHES);
405
            $stringToSign = $url . ":" . $apiKey . ":" . $btpnTimestamp . ":" . $encoderData;
406
        } else {
407
            $stringToSign = $url . ":" . $apiKey . ":" . $btpnTimestamp;
408
        }
409
410
        $auth_signature = hash_hmac('sha256', $stringToSign, $apiSecret, true);
411
        return base64_encode($auth_signature);
412
    }
413
414
    /**
415
     * Set TimeZone.
416
     *
417
     * @param string $timeZone
418
     *
419
     * @return string
420
     */
421
    public static function setTimeZone($timeZone)
422
    {
423
        self::$timezone = $timeZone;
424
    }
425
426
    /**
427
     * Get TimeZone.
428
     *
429
     * @return string
430
     */
431
    public static function getTimeZone()
432
    {
433
        return self::$timezone;
434
    }
435
436
    /**
437
     * Set Jenius Hostname
438
     *
439
     * @param string $hostName
440
     *
441
     * @return string
442
     */
443
    public static function setHostName($hostName)
444
    {
445
        self::$hostName = $hostName;
446
    }
447
448
    /**
449
     * Get Jenius Hostname
450
     *
451
     * @return string
452
     */
453
    public static function getHostName()
454
    {
455
        return self::$hostName;
456
    }
457
458
    /**
459
     * Set Jenius Segment
460
     *
461
     * @param string $segment
462
     *
463
     * @return string
464
     */
465
    public static function setSegment($segment)
466
    {
467
        self::$segment = $segment;
468
    }
469
470
    /**
471
     * Get Jenius Segment
472
     *
473
     * @return string
474
     */
475
    public static function getSegment()
476
    {
477
        return self::$segment;
478
    }
479
480
    /**
481
     * Get Max Execution Time.
482
     *
483
     * @return string
484
     */
485
    public static function getTimeOut()
486
    {
487
        return self::$timeOut;
488
    }
489
490
    /**
491
     * Get Curl Options
492
     *
493
     * @return string
494
     */
495
    public static function getCurlOptions()
496
    {
497
        return self::$curlOptions;
498
    }
499
500
    /**
501
     * Setup Curl Options.
502
     *
503
     * @param array $curlOpts
504
     * @return void
505
     */
506
    public static function setCurlOptions(array $curlOpts = [])
507
    {
508
        $data = self::mergeCurlOptions(self::$curlOptions, $curlOpts);
0 ignored issues
show
Bug introduced by
self::curlOptions of type integer is incompatible with the type array expected by parameter $existing_options of Jenius\JeniusHttp::mergeCurlOptions(). ( Ignorable by Annotation )

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

508
        $data = self::mergeCurlOptions(/** @scrutinizer ignore-type */ self::$curlOptions, $curlOpts);
Loading history...
509
        self::$curlOptions = $data;
0 ignored issues
show
Documentation Bug introduced by
It seems like $data of type array is incompatible with the declared type integer of property $curlOptions.

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...
510
    }
511
512
    /**
513
     * Set Max Execution Time
514
     *
515
     * @param int $timeOut
516
     *
517
     * @return string
518
     */
519
    public static function setTimeOut($timeOut)
520
    {
521
        self::$timeOut = $timeOut;
522
        return self::$timeOut;
523
    }
524
525
    /**
526
     * Set Jenius Port
527
     *
528
     * @param int $port
529
     *
530
     * @return void
531
     */
532
    public static function setPort($port)
533
    {
534
        self::$port = $port;
535
    }
536
537
    /**
538
     * Get Jenius Port
539
     *
540
     * @return int
541
     */
542
    public static function getPort()
543
    {
544
        return self::$port;
545
    }
546
547
    /**
548
     * Set Jenius Scheme
549
     *
550
     * @param int $scheme
551
     *
552
     * @return string
553
     */
554
    public static function setScheme($scheme)
555
    {
556
        self::$scheme = $scheme;
557
    }
558
559
    /**
560
     * Get Jenius Scheme
561
     *
562
     * @return string
563
     */
564
    public static function getScheme()
565
    {
566
        return self::$scheme;
567
    }
568
569
    /**
570
     * Generate ISO8601 Time.
571
     *
572
     * @return string
573
     */
574
    public static function generateBtpnTimestamp()
575
    {
576
        $date = Carbon::now(self::getTimeZone());
577
        date_default_timezone_set(self::getTimeZone());
578
        $fmt = $date->format('Y-m-d\TH:i:s');
579
        $ISO8601 = sprintf("$fmt.%s%s", substr(microtime(), 2, 3), date('P'));
580
581
        return $ISO8601;
582
    }
583
584
    // 2020-09-26T21:14:07
585
    public static function generateOriginalTimestamp($date)
586
    {
587
        $ISO8601 = sprintf("$date.%s%s", substr(microtime(), 2, 3), date('P'));
588
        return $ISO8601;
589
    }
590
591
    /**
592
     * Merge from existing array.
593
     *
594
     * @param array $existing_options
595
     * @param array $new_options
596
     * @return array
597
     */
598
    private static function mergeCurlOptions(&$existing_options, $new_options)
599
    {
600
        $existing_options = $new_options + $existing_options;
601
        return $existing_options;
602
    }
603
604
    /**
605
     * Implode an array with the key and value pair giving
606
     * a glue, a separator between pairs and the array
607
     * to implode.
608
     *
609
     * @param string $glue The glue between key and value
610
     * @param string $separator Separator between pairs
611
     * @param array $array The array to implode
612
     *
613
     * @return string The imploded array
614
     * @throws JeniusHttpException error
615
     */
616
    public static function arrayImplode($glue, $separator, $array = [])
617
    {
618
        if (!is_array($array)) {
0 ignored issues
show
introduced by
The condition is_array($array) is always true.
Loading history...
619
            throw new JeniusHttpException('Data should array.');
620
        }
621
        if (empty($array)) {
622
            throw new JeniusHttpException('Parameter can`t be empty.');
623
        }
624
        foreach ($array as $key => $val) {
625
            if (is_array($val)) {
626
                $val = implode(',', $val);
627
            }
628
            $string[] = "{$key}{$glue}{$val}";
629
        }
630
631
        return implode($separator, $string);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $string seems to be defined by a foreach iteration on line 624. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
632
    }
633
}
634