Passed
Pull Request — master (#136)
by
unknown
03:46 queued 56s
created

Rayanpay::purchase()   B

Complexity

Conditions 6
Paths 20

Size

Total Lines 58
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 6
eloc 36
c 3
b 0
f 0
nc 20
nop 0
dl 0
loc 58
rs 8.7217

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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(
72
            $data,
73
            $this->settings->apiTokenUrl,
74
            'token',
75
            false
76
        );
77
    }
78
79
    /**
80
     * Purchase Invoice.
81
     *
82
     * @return string
83
     *
84
     * @throws PurchaseFailedException
85
     * @throws \GuzzleHttp\Exception\GuzzleException
86
     */
87
    public function purchase()
88
    {
89
        $this->auth();
90
91
        $details = $this->invoice->getDetails();
92
93
        if (!empty($details['mobile'])) {
94
            $mobile = $details['mobile'];
95
        }
96
        if (!empty($details['phone'])) {
97
            $mobile = $details['phone'];
98
        }
99
100
        if (empty($mobile)) {
101
            throw new PurchaseFailedException('شماره موبایل را وارد کنید.');
102
        }
103
104
        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...
105
            $mobile = '';
106
        }
107
108
        if (($this->invoice->getAmount() * 10) <= 1000) {
109
            throw new PurchaseFailedException('مقدار مبلغ ارسالی بزگتر از 1000 باشد.');
110
        }
111
112
        $referenceId = hexdec(uniqid());
113
        $amount = $this->invoice->getAmount();
114
115
        $callback = $this->settings->callbackUrl . "?referenceId=" . $referenceId . "&price=" . $amount . "&mobile=" . $mobile;
116
117
        $data = [
118
            'referenceId' => $referenceId,
119
            'amount' => $amount,
120
            'msisdn' => $mobile,
121
            'gatewayId' => 100,
122
            'callbackUrl' => $callback,
123
            'gateSwitchingAllowed' => true,
124
        ];
125
126
        $response = $this->makeHttpChargeRequest(
127
            $data,
128
            $this->settings->apiPayStart,
129
            'payment_start',
130
            true
131
        );
132
133
        $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

133
        $body = json_decode(/** @scrutinizer ignore-type */ $response, true);
Loading history...
134
135
        $this->invoice->transactionId($referenceId);
136
137
        // Get RefIf From Html Form Becuese GetWay Not Provide In Api
138
        $dom = new \DOMDocument();
139
        $dom->loadHTML($body['bankRedirectHtml']);
140
        $xp = new \DOMXPath($dom);
141
        $nodes = $xp->query('//input[@name="RefId"]');
142
        $node = $nodes->item(0);
143
        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

143
        /** @scrutinizer ignore-call */ 
144
        session()->put('RefId', $node->getAttribute('value'));
Loading history...
144
        return $this->invoice->getTransactionId();
145
    }
146
147
    /**
148
     * Pay the Invoice render html redirect to getway
149
     *
150
     * @return RedirectionForm
151
     */
152
    public function pay(): RedirectionForm
153
    {
154
        return $this->redirectWithForm($this->settings->apiPurchaseUrl, [
155
            'x_GateChanged' => 0,
156
            '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

156
            'RefId' => /** @scrutinizer ignore-call */ session('RefId')
Loading history...
157
        ], 'POST');
158
    }
159
160
    /**
161
     * Verify payment
162
     *
163
     * @return ReceiptInterface
164
     *
165
     * @throws InvalidPaymentException
166
     * @throws \GuzzleHttp\Exception\GuzzleException
167
     */
168
    public function verify(): ReceiptInterface
169
    {
170
        $data = [
171
            'referenceId' => (int)$this->getInvoice()->getTransactionId(),
172
            'header' => '',
173
            'content' => http_build_query($_POST),
174
        ];
175
176
        $response = $this->makeHttpChargeRequest(
177
            $data,
178
            $this->settings->apiPayVerify,
179
            'payment_parse',
180
            true
181
        );
182
183
        $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

183
        $body = json_decode(/** @scrutinizer ignore-type */ $response, true);
Loading history...
184
185
        $receipt = $this->createReceipt($body['paymentId']);
186
187
        $receipt->detail([
188
            'paymentId' => $body['paymentId'],
189
            'hashedBankCardNumber' => $body['hashedBankCardNumber'],
190
            'endDate' => $body['endDate'],
191
        ]);
192
193
        return $receipt;
194
    }
195
196
    /**
197
     * Generate the payment's receipt
198
     *
199
     * @param $referenceId
200
     *
201
     * @return Receipt
202
     */
203
    protected function createReceipt($referenceId)
204
    {
205
        $receipt = new Receipt('rayanpay', $referenceId);
206
207
        return $receipt;
208
    }
209
210
211
    /**
212
     * Trigger an exception
213
     *
214
     * @param $status
215
     * @param $method
216
     * @throws InvalidPaymentException
217
     */
218
    private function notVerified($status, $method)
219
    {
220
        $message = "";
221
        if ($method == 'token') {
222
            switch ($status) {
223
224
                case '400' :
225
                    $message = 'نقص در پارامترهای ارسالی';
226
                    break;
227
228
                case '401' :
229
                    $message = 'کد کاربری/رمز عبور /کلاینت/آی پی نامعتبر است';
230
                    break;
231
232
                case '500' :
233
                    $message = 'خطایی سمت سرور رخ داده است';
234
                    break;
235
            }
236
        } elseif ($method == 'payment_start') {
237
            switch ($status) {
238
                case '400' :
239
                    $message = 'شناسه ارسالی تکراری می باشد ';
240
                    break;
241
                case '401' :
242
                    $message = 'توکن نامعتبر';
243
                    break;
244
245
                case '601' :
246
                    $message = 'اتصال به درگاه خطا دارد (پرداخت ناموفق)';
247
                    break;
248
249
                case '500' :
250
                    $message = 'خطایی سمت سرور رخ داده است (احتمال تکراری بودن شماره ref شما یا اگر شماره موبایل دارید باید فرمت زیر باشد 989121112233 )';
251
                    break;
252
            }
253
        } elseif ($method == 'payment_status') {
254
            switch ($status) {
255
                case '401' :
256
                    $message = 'توکن نامعتبر است';
257
                    break;
258
                case '601' :
259
                    $message = 'پرداخت ناموفق';
260
                    break;
261
262
                case '600' :
263
                    $message = 'پرداخت در حالت Pending می باشد و باید متد fullfill برای تعیین وضعیت صدا زده شود';
264
                    break;
265
            }
266
        } elseif ($method == 'payment_parse') {
267
            switch ($status) {
268
269
                case '401':
270
                    $message = 'توکن نامعتبر است';
271
                    break;
272
273
                case '500':
274
                    $message = 'خطایی سمت سرور رخ داده است';
275
                    break;
276
277
                case '600':
278
                    $message = 'وضعیت نامشخص';
279
                    break;
280
281
                case '601':
282
                    $message = 'پرداخت ناموفق';
283
                    break;
284
285
                case '602':
286
                    $message = 'پرداخت یافت نشد';
287
                    break;
288
289
                case '608':
290
                    $message = 'قوانین پرداخت یافت نشد (برای پرداخت هایی که قوانین دارند)';
291
                    break;
292
293
                case '609':
294
                    $message = 'وضعیت پرداخت نامعتبر میباشد';
295
                    break;
296
            }
297
        }
298
        if ($message) {
299
            throw new InvalidPaymentException($message);
300
        } else {
301
            throw new InvalidPaymentException('خطای ناشناخته ای رخ داده است.' . $method);
302
        }
303
    }
304
305
    private function makeHttpChargeRequest($data, $url, $method, $forAuth = true)
306
    {
307
        $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...
308
        if ($forAuth) {
309
            $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

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