Passed
Push — main ( 6b17f2...1e3b41 )
by Miaad
11:18
created

zarinpal::request()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
eloc 10
c 1
b 0
f 1
nc 1
nop 9
dl 0
loc 11
rs 9.9332

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 BPT\pay;
4
5
use BPT\pay\zarinpal\refundInterface;
6
use BPT\pay\zarinpal\requestInterface;
7
use BPT\pay\zarinpal\unverifiedInterface;
8
use BPT\pay\zarinpal\verifyInterface;
9
use BPT\settings;
10
use CurlHandle;
11
use JetBrains\PhpStorm\NoReturn;
12
13
class zarinpal {
14
    public static string $merchant_id = '';
15
    public static bool $sandbox = false;
16
    public static bool $zarin_gate = false;
17
18
    const API_BASE = 'https://api.zarinpal.com/pg/v4/payment/';
19
20
    const SANDBOX_API_BASE = 'https://sandbox.zarinpal.com/pg/v4/payment/';
21
22
    const PAY_BASE = 'https://www.zarinpal.com/pg/StartPay/';
23
24
    const SANDBOX_PAY_BASE = 'https://sandbox.zarinpal.com/pg/StartPay/';
25
26
    private static CurlHandle $session;
27
28
    public static function init (string $merchant_id = '', bool $sandbox = false, bool $zarin_gate = false): void {
29
        self::$sandbox = settings::$pay['zarinpal']['sandbox'] ?? $sandbox;
30
        self::$zarin_gate = settings::$pay['zarinpal']['zarin_gate'] ?? settings::$pay['zarinpal']['zaringate'] ?? $zarin_gate;
31
        self::$merchant_id = settings::$pay['zarinpal']['merchant_id'] ?? $merchant_id;
32
        self::$session = curl_init();
33
        curl_setopt(self::$session, CURLOPT_RETURNTRANSFER, true);
34
        curl_setopt(self::$session, CURLOPT_SSL_VERIFYPEER, 1);
35
        curl_setopt(self::$session, CURLOPT_SSL_VERIFYHOST, 2);
36
        curl_setopt(self::$session, CURLOPT_HTTPHEADER, [
37
            'Content-Type: application/json',
38
            'Accept: application/json'
39
        ]);
40
        curl_setopt(self::$session, CURLOPT_POST, true);
41
    }
42
43
    private static function getUrl (string $endpoint, bool $pay = false): string {
44
        if ($pay) {
45
            $url = self::$sandbox ? self::SANDBOX_PAY_BASE : self::PAY_BASE;
46
        }
47
        else {
48
            $url = self::$sandbox ? self::SANDBOX_API_BASE : self::API_BASE;
49
        }
50
        $url .= $endpoint;
51
        if (self::$zarin_gate) {
52
            $url .= '/ZarinGate';
53
        }
54
        return $url;
55
    }
56
57
    private static function execute (string $endpoint, array $params = []): object {
58
        foreach ($params as $key => $value) {
59
            if (empty($value)) {
60
                unset($params[$key]);
61
            }
62
        }
63
64
        $session = self::$session;
65
66
        $params['merchant_id'] = self::$merchant_id;
67
68
        if (isset($params['authorization'])) {
69
            curl_setopt(self::$session, CURLOPT_HTTPHEADER, [
70
                'Content-Type: application/json',
71
                'Accept: application/json',
72
                'authorization: Bearer '.$params['authorization']
73
            ]);
74
            unset($params['authorization']);
75
        }
76
77
        curl_setopt($session, CURLOPT_POSTFIELDS, json_encode($params));
78
        curl_setopt($session, CURLOPT_URL, self::getUrl($endpoint));
79
80
        $result = json_decode(curl_exec($session));
0 ignored issues
show
Bug introduced by
It seems like curl_exec($session) can also be of type true; however, parameter $json of json_decode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

80
        $result = json_decode(/** @scrutinizer ignore-type */ curl_exec($session));
Loading history...
81
        if (isset($result->data)) {
82
            return $result->data;
83
        }
84
85
        return $result;
86
    }
87
88
    /**
89
     * @return object|requestInterface
90
     */
91
    public static function request (int $amount, string $description, string $callback_url, array $metadata = [], string $mobile = '', string $email = '', array $wages = [], int $card_pan = null, string $currency = ''): object {
92
        return self::execute('/request.json', [
93
            'amount'       => $amount,
94
            'description'  => $description,
95
            'callback_url' => $callback_url,
96
            'metadata'     => $metadata,
97
            'mobile'       => $mobile,
98
            'email'        => $email,
99
            'wages'        => $wages,
100
            'card_pan'     => $card_pan,
101
            'currency'     => $currency,
102
        ]);
103
    }
104
105
    public static function payURL (string|array $authority): bool|string {
106
        if (is_array($authority)) {
0 ignored issues
show
introduced by
The condition is_array($authority) is always true.
Loading history...
107
            if (!isset($authority->authority)) {
108
                return false;
109
            }
110
            $authority = $authority->authority;
111
        }
112
        return self::getUrl("/$authority", true);
113
    }
114
115
    /**
116
     * @return object|verifyInterface
117
     */
118
    public static function verify (int $amount, string $authority): object {
119
        return self::execute('/verify.json', [
120
            'amount'    => $amount,
121
            'authority' => $authority
122
        ]);
123
    }
124
125
    /**
126
     * @return object|unverifiedInterface
127
     */
128
    public static function unVerified (): object {
129
        return self::execute('/unVerified.json');
130
    }
131
132
    /**
133
     * @return object|refundInterface
134
     */
135
    public static function refund (string $authorization, string $authority): object {
136
        return self::execute('/refund.json', [
137
            'authorization' => $authorization,
138
            'authority'     => $authority
139
        ]);
140
    }
141
142
    #[NoReturn]
143
    public static function redirect (string $url): void {
144
        @header('Location: ' . $url);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for header(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

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

144
        /** @scrutinizer ignore-unhandled */ @header('Location: ' . $url);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
Bug introduced by
Are you sure the usage of header('Location: ' . $url) is correct as it seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
145
        die("<meta http-equiv='refresh' content='0; url=$url' /><script>window.location.href = '$url';</script>");
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
146
    }
147
148
    public static function processCallback (int $amount): object|bool|int {
149
        if (!isset($_GET['Authority']) || !isset($_GET['Status'])) {
150
            return false;
151
        }
152
153
        if ($_GET['status'] != 'OK') {
154
            return false;
155
        }
156
157
        $detail = self::verify($amount, $_GET['Authority']);
158
159
        if (isset($detail->code) && $detail->code != 100) {
160
            return $detail->code;
161
        }
162
163
        return $detail;
164
    }
165
}
166