BPTproto /
BPT-Multi
| 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 CurlHandle; |
||||
| 10 | use JetBrains\PhpStorm\NoReturn; |
||||
| 11 | |||||
| 12 | class zarinpal { |
||||
| 13 | public static string $merchant_id = ''; |
||||
| 14 | public static bool $sandbox = false; |
||||
| 15 | public static bool $zarin_gate = false; |
||||
| 16 | |||||
| 17 | const API_BASE = 'https://api.zarinpal.com/pg/v4/payment/'; |
||||
| 18 | |||||
| 19 | const SANDBOX_API_BASE = 'https://sandbox.zarinpal.com/pg/v4/payment/'; |
||||
| 20 | |||||
| 21 | const PAY_BASE = 'https://www.zarinpal.com/pg/StartPay/'; |
||||
| 22 | |||||
| 23 | const SANDBOX_PAY_BASE = 'https://sandbox.zarinpal.com/pg/StartPay/'; |
||||
| 24 | |||||
| 25 | private static CurlHandle $session; |
||||
| 26 | |||||
| 27 | public static function init (string $merchant_id = '', bool $sandbox = false, bool $zarin_gate = false): void { |
||||
| 28 | self::$sandbox = $sandbox; |
||||
| 29 | self::$zarin_gate = $zarin_gate; |
||||
| 30 | self::$merchant_id = $merchant_id; |
||||
| 31 | self::$session = curl_init(); |
||||
| 32 | curl_setopt(self::$session, CURLOPT_RETURNTRANSFER, true); |
||||
| 33 | curl_setopt(self::$session, CURLOPT_SSL_VERIFYPEER, 1); |
||||
| 34 | curl_setopt(self::$session, CURLOPT_SSL_VERIFYHOST, 2); |
||||
| 35 | curl_setopt(self::$session, CURLOPT_HTTPHEADER, [ |
||||
| 36 | 'Content-Type: application/json', |
||||
| 37 | 'Accept: application/json' |
||||
| 38 | ]); |
||||
| 39 | curl_setopt(self::$session, CURLOPT_POST, true); |
||||
| 40 | } |
||||
| 41 | |||||
| 42 | private static function getUrl (string $endpoint, bool $pay = false): string { |
||||
| 43 | if ($pay) { |
||||
| 44 | $url = self::$sandbox ? self::SANDBOX_PAY_BASE : self::PAY_BASE; |
||||
| 45 | } |
||||
| 46 | else { |
||||
| 47 | $url = self::$sandbox ? self::SANDBOX_API_BASE : self::API_BASE; |
||||
| 48 | } |
||||
| 49 | $url .= $endpoint; |
||||
| 50 | if (self::$zarin_gate) { |
||||
| 51 | $url .= '/ZarinGate'; |
||||
| 52 | } |
||||
| 53 | return $url; |
||||
| 54 | } |
||||
| 55 | |||||
| 56 | private static function execute (string $endpoint, array $params = []): object { |
||||
| 57 | foreach ($params as $key => $value) { |
||||
| 58 | if (empty($value)) { |
||||
| 59 | unset($params[$key]); |
||||
| 60 | } |
||||
| 61 | } |
||||
| 62 | |||||
| 63 | $session = self::$session; |
||||
| 64 | |||||
| 65 | $params['merchant_id'] = self::$merchant_id; |
||||
| 66 | |||||
| 67 | if (isset($params['authorization'])) { |
||||
| 68 | curl_setopt(self::$session, CURLOPT_HTTPHEADER, [ |
||||
| 69 | 'Content-Type: application/json', |
||||
| 70 | 'Accept: application/json', |
||||
| 71 | 'authorization: Bearer '.$params['authorization'] |
||||
| 72 | ]); |
||||
| 73 | unset($params['authorization']); |
||||
| 74 | } |
||||
| 75 | |||||
| 76 | curl_setopt($session, CURLOPT_POSTFIELDS, json_encode($params)); |
||||
| 77 | curl_setopt($session, CURLOPT_URL, self::getUrl($endpoint)); |
||||
| 78 | |||||
| 79 | $result = json_decode(curl_exec($session)); |
||||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||
| 80 | if (isset($result->data)) { |
||||
| 81 | return $result->data; |
||||
| 82 | } |
||||
| 83 | |||||
| 84 | return $result; |
||||
| 85 | } |
||||
| 86 | |||||
| 87 | /** |
||||
| 88 | * @return object|requestInterface |
||||
| 89 | */ |
||||
| 90 | 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 { |
||||
| 91 | return self::execute('/request.json', [ |
||||
| 92 | 'amount' => $amount, |
||||
| 93 | 'description' => $description, |
||||
| 94 | 'callback_url' => $callback_url, |
||||
| 95 | 'metadata' => $metadata, |
||||
| 96 | 'mobile' => $mobile, |
||||
| 97 | 'email' => $email, |
||||
| 98 | 'wages' => $wages, |
||||
| 99 | 'card_pan' => $card_pan, |
||||
| 100 | 'currency' => $currency, |
||||
| 101 | ]); |
||||
| 102 | } |
||||
| 103 | |||||
| 104 | public static function payURL (string|array $authority): bool|string { |
||||
| 105 | if (is_array($authority)) { |
||||
|
0 ignored issues
–
show
|
|||||
| 106 | if (!isset($authority->authority)) { |
||||
| 107 | return false; |
||||
| 108 | } |
||||
| 109 | $authority = $authority->authority; |
||||
| 110 | } |
||||
| 111 | return self::getUrl("/$authority", true); |
||||
| 112 | } |
||||
| 113 | |||||
| 114 | /** |
||||
| 115 | * @return object|verifyInterface |
||||
| 116 | */ |
||||
| 117 | public static function verify (int $amount, string $authority): object { |
||||
| 118 | return self::execute('/verify.json', [ |
||||
| 119 | 'amount' => $amount, |
||||
| 120 | 'authority' => $authority |
||||
| 121 | ]); |
||||
| 122 | } |
||||
| 123 | |||||
| 124 | /** |
||||
| 125 | * @return object|unverifiedInterface |
||||
| 126 | */ |
||||
| 127 | public static function unVerified (): object { |
||||
| 128 | return self::execute('/unVerified.json'); |
||||
| 129 | } |
||||
| 130 | |||||
| 131 | /** |
||||
| 132 | * @return object|refundInterface |
||||
| 133 | */ |
||||
| 134 | public static function refund (string $authorization, string $authority): object { |
||||
| 135 | return self::execute('/refund.json', [ |
||||
| 136 | 'authorization' => $authorization, |
||||
| 137 | 'authority' => $authority |
||||
| 138 | ]); |
||||
| 139 | } |
||||
| 140 | |||||
| 141 | #[NoReturn] |
||||
| 142 | public static function redirect (string $url): void { |
||||
| 143 | @header('Location: ' . $url); |
||||
|
0 ignored issues
–
show
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 The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. Loading history...
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
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...
|
|||||
| 144 | die("<meta http-equiv='refresh' content='0; url=$url' /><script>window.location.href = '$url';</script>"); |
||||
|
0 ignored issues
–
show
|
|||||
| 145 | } |
||||
| 146 | |||||
| 147 | public static function processCallback (int $amount): object|bool|int { |
||||
| 148 | if (!isset($_GET['Authority']) || !isset($_GET['Status'])) { |
||||
| 149 | return false; |
||||
| 150 | } |
||||
| 151 | |||||
| 152 | if ($_GET['status'] != 'OK') { |
||||
| 153 | return false; |
||||
| 154 | } |
||||
| 155 | |||||
| 156 | $detail = self::verify($amount, $_GET['Authority']); |
||||
| 157 | |||||
| 158 | if (isset($detail->code) && $detail->code != 100) { |
||||
| 159 | return $detail->code; |
||||
| 160 | } |
||||
| 161 | |||||
| 162 | return $detail; |
||||
| 163 | } |
||||
| 164 | } |
||||
| 165 |