Passed
Pull Request — master (#136)
by
unknown
08:18
created

Rayanpay::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 8
rs 10
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\Rayanpay;
4
5
use GuzzleHttp\Client;
6
use Shetabit\Multipay\Abstracts\Driver;
7
use Shetabit\Multipay\Contracts\ReceiptInterface;
8
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
9
use Shetabit\Multipay\Exceptions\PurchaseFailedException;
10
use Shetabit\Multipay\Invoice;
11
use Shetabit\Multipay\Receipt;
12
use Shetabit\Multipay\RedirectionForm;
13
14
class Rayanpay extends Driver
15
{
16
    /**
17
     * Sadad Client.
18
     *
19
     * @var object
20
     */
21
    protected $client;
22
23
    /**
24
     * Invoice
25
     *
26
     * @var Invoice
27
     */
28
    protected $invoice;
29
30
    /**
31
     * Driver settings
32
     *
33
     * @var object
34
     */
35
    protected $settings;
36
37
    /**
38
     * Open Gate By Render Html
39
     * @var string $htmlPay
40
     */
41
42
    /**
43
     * Sadad constructor.
44
     * Construct the class with the relevant settings.
45
     *
46
     * @param Invoice $invoice
47
     * @param $settings
48
     */
49
    public function __construct(Invoice $invoice, $settings)
50
    {
51
        $this->invoice($invoice);
52
        $this->settings = (object)$settings;
53
        $this->client = new Client(
54
            [
55
                'base_uri' => $this->settings->apiPurchaseUrl,
56
                'verify' => false
57
            ]
58
        );
59
    }
60
61
    /**
62
     * @throws InvalidPaymentException
63
     */
64
    private function auth()
65
    {
66
        $data = [
67
            'clientId' => $this->settings->client_id,
68
            'userName' => $this->settings->username,
69
            'password' => $this->settings->password,
70
        ];
71
        return $this->makeHttpChargeRequest($data, $this->settings->apiTokenUrl, 'token', false);
72
    }
73
74
    /**
75
     * Purchase Invoice.
76
     *
77
     * @return string
78
     *
79
     * @throws PurchaseFailedException
80
     * @throws \GuzzleHttp\Exception\GuzzleException
81
     */
82
    public function purchase()
83
    {
84
        $this->auth();
85
86
        $details = $this->invoice->getDetails();
87
88
        if (!empty($details['mobile'])) {
89
            $mobile = $details['mobile'];
90
        }
91
        if (!empty($details['phone'])) {
92
            $mobile = $details['phone'];
93
        }
94
95
        if (empty($mobile)) {
96
            throw new PurchaseFailedException('شماره موبایل را وارد کنید.');
97
        }
98
99
        if (preg_match('/^(?:98)?9[0-9]{9}$/', $mobile) == false) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $mobile does not seem to be defined for all execution paths leading up to this point.
Loading history...
Bug Best Practice introduced by
It seems like you are loosely comparing preg_match('/^(?:98)?9[0-9]{9}$/', $mobile) of type integer to the boolean false. If you are specifically checking for 0, consider using something more explicit like === 0 instead.
Loading history...
100
            $mobile = '';
101
        }
102
103
        if (($this->invoice->getAmount() * 10) <= 1000) {
104
            throw new PurchaseFailedException('مقدار مبلغ ارسالی بزگتر از 1000 باشد.');
105
        }
106
107
        $referenceId = hexdec(uniqid());
108
        $amount = $this->invoice->getAmount();
109
110
        $callback = $this->settings->callbackUrl . "?referenceId=" . $referenceId . "&price=" . $amount . "&mobile=" . $mobile;
111
112
        $data = [
113
            'referenceId' => $referenceId,
114
            'amount' => $amount,
115
            'msisdn' => $mobile,
116
            'gatewayId' => 100,
117
            'callbackUrl' => $callback,
118
            'gateSwitchingAllowed' => true,
119
        ];
120
121
        $response = $this->makeHttpChargeRequest(
122
            $data,
123
            $this->settings->apiPayStart,
124
            'payment_start',
125
            true);
126
127
        $body = json_decode($response, true);
0 ignored issues
show
Bug introduced by
It seems like $response 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

127
        $body = json_decode(/** @scrutinizer ignore-type */ $response, true);
Loading history...
128
129
        $this->invoice->transactionId($referenceId);
130
131
        // Get RefIf From Html Form Becuese GetWay Not Provide In Api
132
        $dom = new \DOMDocument();
133
        $dom->loadHTML($body['bankRedirectHtml']);
134
        $xp = new \DOMXPath($dom);
135
        $nodes = $xp->query('//input[@name="RefId"]');
136
        $node = $nodes->item(0);
137
        session()->put('RefId', $node->getAttribute('value'));
0 ignored issues
show
Bug introduced by
The function session was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

137
        /** @scrutinizer ignore-call */ 
138
        session()->put('RefId', $node->getAttribute('value'));
Loading history...
138
        return $this->invoice->getTransactionId();
139
    }
140
141
    /**
142
     * Pay the Invoice render html redirect to getway
143
     *
144
     * @return RedirectionForm
145
     */
146
    public function pay(): RedirectionForm
147
    {
148
        return $this->redirectWithForm($this->settings->apiPurchaseUrl, [
149
            'x_GateChanged' => 0,
150
            'RefId' => session('RefId')
0 ignored issues
show
Bug introduced by
The function session was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

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

150
            'RefId' => /** @scrutinizer ignore-call */ session('RefId')
Loading history...
151
        ], 'POST');
152
    }
153
154
    /**
155
     * Verify payment
156
     *
157
     * @return ReceiptInterface
158
     *
159
     * @throws InvalidPaymentException
160
     * @throws \GuzzleHttp\Exception\GuzzleException
161
     */
162
    public function verify(): ReceiptInterface
163
    {
164
        $data = [
165
            'referenceId' => (int)$this->getInvoice()->getTransactionId(),
166
            'header' => '',
167
            'content' => http_build_query($_POST),
168
        ];
169
170
        $response = $this->makeHttpChargeRequest(
171
            $data,
172
            $this->settings->apiPayVerify,
173
            'payment_parse',
174
            true
175
        );
176
177
        $body = json_decode($response, true);
0 ignored issues
show
Bug introduced by
It seems like $response 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

177
        $body = json_decode(/** @scrutinizer ignore-type */ $response, true);
Loading history...
178
179
        $receipt = $this->createReceipt($body['paymentId']);
180
181
        $receipt->detail([
182
            'paymentId' => $body['paymentId'],
183
            'hashedBankCardNumber' => $body['hashedBankCardNumber'],
184
            'endDate' => $body['endDate'],
185
        ]);
186
187
        return $receipt;
188
    }
189
190
    /**
191
     * Generate the payment's receipt
192
     *
193
     * @param $referenceId
194
     *
195
     * @return Receipt
196
     */
197
    protected function createReceipt($referenceId)
198
    {
199
        $receipt = new Receipt('rayanpay', $referenceId);
200
201
        return $receipt;
202
    }
203
204
205
    /**
206
     * Trigger an exception
207
     *
208
     * @param $status
209
     * @param $method
210
     * @throws InvalidPaymentException
211
     */
212
    private function notVerified($status, $method)
213
    {
214
        $message = "";
215
        if ($method == 'token') {
216
            switch ($status) {
217
218
                case '400' :
219
                    $message = 'نقص در پارامترهای ارسالی';
220
                    break;
221
222
                case '401' :
223
                    $message = 'کد کاربری/رمز عبور /کلاینت/آی پی نامعتبر است';
224
                    break;
225
226
                case '500' :
227
                    $message = 'خطایی سمت سرور رخ داده است';
228
                    break;
229
            }
230
        } elseif ($method == 'payment_start') {
231
            switch ($status) {
232
                case '400' :
233
                    $message = 'شناسه ارسالی تکراری می باشد ';
234
                    break;
235
                case '401' :
236
                    $message = 'توکن نامعتبر';
237
                    break;
238
239
                case '601' :
240
                    $message = 'اتصال به درگاه خطا دارد (پرداخت ناموفق)';
241
                    break;
242
243
                case '500' :
244
                    $message = 'خطایی سمت سرور رخ داده است (احتمال تکراری بودن شماره ref شما یا اگر شماره موبایل دارید باید فرمت زیر باشد 989121112233 )';
245
                    break;
246
            }
247
248
        } elseif ($method == 'payment_status') {
249
            switch ($status) {
250
                case '401' :
251
                    $message = 'توکن نامعتبر است';
252
                    break;
253
                case '601' :
254
                    $message = 'پرداخت ناموفق';
255
                    break;
256
257
                case '600' :
258
                    $message = 'پرداخت در حالت Pending می باشد و باید متد fullfill برای تعیین وضعیت صدا زده شود';
259
                    break;
260
            }
261
262
        } elseif ($method == 'payment_parse') {
263
            switch ($status) {
264
265
                case '401' :
266
                    $message = 'توکن نامعتبر است';
267
                    break;
268
269
                case '500' :
270
                    $message = 'خطایی سمت سرور رخ داده است';
271
                    break;
272
273
                case '600' :
274
                    $message = 'وضعیت نامشخص';
275
                    break;
276
277
                case '601' :
278
                    $message = 'پرداخت ناموفق';
279
                    break;
280
281
                case '602' :
282
                    $message = 'پرداخت یافت نشد';
283
                    break;
284
285
                case '608' :
286
                    $message = 'قوانین پرداخت یافت نشد (برای پرداخت هایی که قوانین دارند)';
287
                    break;
288
289
                case '609' :
290
                    $message = 'وضعیت پرداخت نامعتبر میباشد';
291
                    break;
292
            }
293
        }
294
        if ($message) {
295
            throw new InvalidPaymentException($message);
296
        } else {
297
            throw new InvalidPaymentException('خطای ناشناخته ای رخ داده است.' . $method);
298
        }
299
    }
300
301
    private function makeHttpChargeRequest($data, $url, $method, $forAuth = true)
302
    {
303
        $header[] = 'Content-Type: application/json';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$header was never initialized. Although not strictly required by PHP, it is generally a good practice to add $header = array(); before regardless.
Loading history...
304
        if ($forAuth) {
305
            $header[] = 'Authorization: Bearer ' . $this->auth();
0 ignored issues
show
Bug introduced by
Are you sure $this->auth() of type string|true can be used in concatenation? ( Ignorable by Annotation )

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

305
            $header[] = 'Authorization: Bearer ' . /** @scrutinizer ignore-type */ $this->auth();
Loading history...
306
        }
307
        $ch = curl_init($url);
308
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
309
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
310
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
311
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
312
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
313
        $result = curl_exec($ch);
314
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
315
        curl_close($ch);
316
        if ($http_code != 200) {
317
            return $this->notVerified($http_code, $method);
318
        }
319
        return $result;
320
    }
321
322
}
323