Passed
Pull Request — master (#32)
by
unknown
02:04
created

Payping   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 394
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 162
c 1
b 0
f 0
dl 0
loc 394
rs 10
wmc 26

13 Methods

Rating   Name   Duplication   Size   Complexity  
A convertStatusCodeToMessage() 0 14 1
A createMultiRequest() 0 40 3
A purchase() 0 46 3
A createSingleRequest() 0 43 3
A __construct() 0 5 1
A verify() 0 33 3
A notVerified() 0 3 1
A pay() 0 5 1
A extractDetails() 0 3 2
A createReceipt() 0 5 1
A verifyPayment() 0 30 2
A getClientUserProfile() 0 26 3
A call() 0 7 2
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\Payping;
4
5
use GuzzleHttp\Client;
6
use Shetabit\Multipay\Abstracts\Driver;
7
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
8
use Shetabit\Multipay\Exceptions\PurchaseFailedException;
9
use Shetabit\Multipay\Contracts\ReceiptInterface;
10
use Shetabit\Multipay\Invoice;
11
use Shetabit\Multipay\Receipt;
12
use Shetabit\Multipay\RedirectionForm;
13
use Shetabit\Multipay\Request;
14
15
class Payping extends Driver
16
{
17
    /**
18
     * Payping Client.
19
     *
20
     * @var object
21
     */
22
    protected $client;
23
24
    /**
25
     * Invoice
26
     *
27
     * @var Invoice
28
     */
29
    protected $invoice;
30
31
    /**
32
     * Driver settings
33
     *
34
     * @var object
35
     */
36
    protected $settings;
37
38
    /**
39
     * Driver userInfoUrl
40
     *
41
     * @var object
42
     */
43
    protected $userInfoUrl;
44
45
    /**
46
     * Payping constructor.
47
     * Construct the class with the relevant settings.
48
     *
49
     * @param Invoice $invoice
50
     * @param $settings
51
     */
52
    public function __construct(Invoice $invoice, $settings)
53
    {
54
        $this->invoice($invoice);
55
        $this->settings = (object) $settings;
56
        $this->client = new Client();
57
    }
58
59
    /**
60
     * Retrieve data from details using its name.
61
     *
62
     * @return string
63
     */
64
    private function extractDetails($name)
65
    {
66
        return empty($this->invoice->getDetails()[$name]) ? null : $this->invoice->getDetails()[$name];
67
    }
68
69
    /**
70
     * Create payment request as single.
71
     *
72
     * @return data
0 ignored issues
show
Bug introduced by
The type Shetabit\Multipay\Drivers\Payping\data was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
73
     */
74
    private function createSingleRequest($data = array())
75
    {
76
        $data = [
77
            'payerName' => 'bdok',
78
            'amount'         => $data['amount'],
79
            'payerIdentity' => $data['userName'],
80
            'returnUrl'     => $data['returnUrl'],
81
            'clientRefId' => $data['clientRefId'],
82
            'description' => $data['description']
83
        ];
84
85
        $response = $this
86
            ->client
87
            ->request(
88
                'POST',
89
                'https://api.payping.ir/v1/pay',
90
                [
91
                    'json' => $data,
92
                    "headers" => [
93
                        "Accept" => "application/json",
94
                        "Authorization" => sprintf('Bearer %s', $this->settings->accessToken),
95
                    ],
96
                    "http_errors" => false,
97
                ]
98
            );
99
100
        $responseBody = mb_strtolower($response->getBody()->getContents());
101
        $body = @json_decode($responseBody, true);
102
        $statusCode = (int) $response->getStatusCode();
103
104
        if ($statusCode !== 200) {
105
            // some error has happened
106
            $message = is_array($body) ? array_pop($body) : $this->convertStatusCodeToMessage($statusCode);
107
            throw new PurchaseFailedException($message);
108
        }
109
110
        $minutes = now()->addSecond(60 * 5);
0 ignored issues
show
Bug introduced by
The function now 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

110
        $minutes = /** @scrutinizer ignore-call */ now()->addSecond(60 * 5);
Loading history...
111
        cache(['transactionId' => $body['code']], $minutes);
0 ignored issues
show
Bug introduced by
The function cache 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

111
        /** @scrutinizer ignore-call */ 
112
        cache(['transactionId' => $body['code']], $minutes);
Loading history...
112
113
        $this->invoice->transactionId($body['code']);
114
115
        // return the transaction's id
116
        return $this->invoice->getTransactionId();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->invoice->getTransactionId() returns the type string which is incompatible with the documented return type Shetabit\Multipay\Drivers\Payping\data.
Loading history...
117
118
    }
119
120
    /**
121
     * Verify payment.
122
     *
123
     * @return data
124
     */
125
    private function verifyPayment($data = array())
126
    {
127
        $pAccessToken = $data['pAccessToken'];
128
        $data = [
129
            'refId' => $data['refid'],
130
            'amount' => $data['orgAmount']
131
        ];
132
        $response = $this
133
            ->client
134
            ->request(
135
                'POST',
136
                'https://api.payping.ir/v1/pay/verify',
137
                [
138
                    'json' => $data,
139
                    "headers" => [
140
                        "Accept" => "application/json",
141
                        "Authorization" => sprintf('Bearer %s', $pAccessToken),
142
                    ],
143
                    "http_errors" => false,
144
                ]
145
            );
146
147
        $responseBody = mb_strtolower($response->getBody()->getContents());
148
        $body = @json_decode($responseBody, true);
149
        $statusCode = (int) $response->getStatusCode();
150
151
        if ($statusCode != 200)
152
            return 'err';
0 ignored issues
show
Bug Best Practice introduced by
The expression return 'err' returns the type string which is incompatible with the documented return type Shetabit\Multipay\Drivers\Payping\data.
Loading history...
153
154
        return $body;
155
    }
156
157
    /**
158
     * Create request payment as multi request.
159
     *
160
     * @return data
161
     */
162
    private function createMultiRequest($data = array())
163
    {
164
        $data = [
165
            'payerName' => 'bdok',
166
            'pairs'         => $data['pairs'],
167
            'returnUrl'     => $data['returnUrl'],
168
            'clientRefId' => $data['clientRefId']
169
        ];
170
171
        $response = $this
172
            ->client
173
            ->request(
174
                'POST',
175
                'https://api.payping.ir/v1/pay',
176
                [
177
                    'json' => $data,
178
                    "headers" => [
179
                        "Accept" => "application/json",
180
                        "Authorization" => sprintf('Bearer %s', $this->settings->accessToken),
181
                    ],
182
                    "http_errors" => false,
183
                ]
184
            );
185
186
        $responseBody = mb_strtolower($response->getBody()->getContents());
187
        $body = @json_decode($responseBody, true);
188
        $statusCode = (int) $response->getStatusCode();
189
190
        if ($statusCode !== 200) {
191
            $message = is_array($body) ? array_pop($body) : $this->convertStatusCodeToMessage($statusCode);
192
            throw new PurchaseFailedException($message);
193
        }
194
195
        $minutes = now()->addSecond(60 * 5);
0 ignored issues
show
Bug introduced by
The function now 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

195
        $minutes = /** @scrutinizer ignore-call */ now()->addSecond(60 * 5);
Loading history...
196
        cache(['transactionId' => $body['code']], $minutes);
0 ignored issues
show
Bug introduced by
The function cache 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

196
        /** @scrutinizer ignore-call */ 
197
        cache(['transactionId' => $body['code']], $minutes);
Loading history...
197
198
        $this->invoice->transactionId($body['code']);
199
200
        // return the transaction's id
201
        return $this->invoice->getTransactionId();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->invoice->getTransactionId() returns the type string which is incompatible with the documented return type Shetabit\Multipay\Drivers\Payping\data.
Loading history...
202
    }
203
204
    /**
205
     * Get client user profile.
206
     *
207
     * @return data
208
     */
209
    private function getClientUserProfile($data = array())
210
    {
211
        $response = $this
212
            ->client
213
            ->request(
214
                'GET',
215
                'https://oauth.payping.ir/connect/userinfo',
216
                [
217
                    "headers" => [
218
                        "Accept" => "application/json",
219
                        "Authorization" => sprintf('Bearer %s', $this->settings->accessToken),
220
                    ],
221
                    "http_errors" => false,
222
                ]
223
            );
224
225
        $responseBody = mb_strtolower($response->getBody()->getContents());
226
        $body = @json_decode($responseBody);
227
        $statusCode = (int) $response->getStatusCode();
228
229
        if ($statusCode !== 200) {
230
            // some error has happened
231
            $message = is_array($body) ? array_pop($body) : $this->convertStatusCodeToMessage($statusCode);
232
            throw new PurchaseFailedException($message);
233
        }
234
        return $body;
235
    }
236
237
    /**
238
     * Cal custome function.
239
     *
240
     * @return data
241
     */
242
    public function call($method, $data = array())
243
    {
244
        if (method_exists($this, $method))
245
        {
246
            return $this->$method($data);
247
        }
248
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type Shetabit\Multipay\Drivers\Payping\data.
Loading history...
249
    }
250
251
    /**
252
     * Purchase Invoice.
253
     *
254
     * @return string
255
     *
256
     * @throws PurchaseFailedException
257
     * @throws \GuzzleHttp\Exception\GuzzleException
258
     */
259
    public function purchase()
260
    {
261
        $name = $this->extractDetails('name');
262
        $mobile = $this->extractDetails('mobile');
263
        $email = $this->extractDetails('email');
264
        $description = $this->extractDetails('description');
265
266
        $data = array(
267
            "payerName" => $name,
268
            "amount" => $this->invoice->getAmount(),
269
            "payerIdentity" => $mobile ?? $email,
270
            "returnUrl" => $this->settings->callbackUrl,
271
            "description" => $description,
272
            "clientRefId" => $this->invoice->getUuid(),
273
        );
274
275
        $response = $this
276
            ->client
277
            ->request(
278
                'POST',
279
                $this->settings->apiPurchaseUrl,
280
                [
281
                    "json" => $data,
282
                    "headers" => [
283
                        "Accept" => "application/json",
284
                        "Authorization" => "bearer ".$this->settings->merchantId,
285
                    ],
286
                    "http_errors" => false,
287
                ]
288
            );
289
290
        $responseBody = mb_strtolower($response->getBody()->getContents());
291
        $body = @json_decode($responseBody, true);
292
        $statusCode = (int) $response->getStatusCode();
293
294
        if ($statusCode !== 200) {
295
            // some error has happened
296
            $message = is_array($body) ? array_pop($body) : $this->convertStatusCodeToMessage($statusCode);
297
298
            throw new PurchaseFailedException($message);
299
        }
300
301
        $this->invoice->transactionId($body['code']);
302
303
        // return the transaction's id
304
        return $this->invoice->getTransactionId();
305
    }
306
307
    /**
308
     * Pay the Invoice
309
     *
310
     * @return RedirectionForm
311
     */
312
    public function pay() : RedirectionForm
313
    {
314
        $payUrl = $this->settings->apiPaymentUrl.$this->invoice->getTransactionId();
315
316
        return $this->redirectWithForm($payUrl, [], 'GET');
317
    }
318
319
    /**
320
     * Verify payment
321
     *
322
     * @return ReceiptInterface
323
     *
324
     * @throws InvalidPaymentException
325
     * @throws \GuzzleHttp\Exception\GuzzleException
326
     */
327
    public function verify() : ReceiptInterface
328
    {
329
        $refId = Request::input('refid');
330
        $data = [
331
            'amount' => $this->invoice->getAmount(),
332
            'refId'  => $refId,
333
        ];
334
335
        $response = $this->client->request(
336
            'POST',
337
            $this->settings->apiVerificationUrl,
338
            [
339
                'json' => $data,
340
                "headers" => [
341
                    "Accept" => "application/json",
342
                    "Authorization" => "bearer ".$this->settings->merchantId,
343
                ],
344
                "http_errors" => false,
345
            ]
346
        );
347
348
        $responseBody = mb_strtolower($response->getBody()->getContents());
349
        $body = @json_decode($responseBody, true);
350
351
        $statusCode = (int) $response->getStatusCode();
352
353
        if ($statusCode !== 200) {
354
            $message = is_array($body) ? array_pop($body) : $this->convertStatusCodeToMessage($statusCode);
355
356
            $this->notVerified($message);
357
        }
358
359
        return $this->createReceipt($refId);
360
    }
361
362
    /**
363
     * Generate the payment's receipt
364
     *
365
     * @param $referenceId
366
     *
367
     * @return Receipt
368
     */
369
    protected function createReceipt($referenceId)
370
    {
371
        $receipt = new Receipt('payping', $referenceId);
372
373
        return $receipt;
374
    }
375
376
    /**
377
     * Trigger an exception
378
     *
379
     * @param $message
380
     *
381
     * @throws InvalidPaymentException
382
     */
383
    private function notVerified($message)
384
    {
385
        throw new InvalidPaymentException($message);
386
    }
387
388
    /**
389
     * Retrieve related message to given status code
390
     *
391
     * @param $statusCode
392
     *
393
     * @return string
394
     */
395
    private function convertStatusCodeToMessage(int $statusCode) : string
396
    {
397
        $messages = [
398
            400 => 'مشکلی در ارسال درخواست وجود دارد',
399
            401 => 'عدم دسترسی',
400
            403 => 'دسترسی غیر مجاز',
401
            404 => 'آیتم درخواستی مورد نظر موجود نمی باشد',
402
            500 => 'مشکلی در سرور درگاه پرداخت رخ داده است',
403
            503 => 'سرور درگاه پرداخت در حال حاضر قادر به پاسخگویی نمی باشد',
404
        ];
405
406
        $unknown = 'خطای ناشناخته ای در درگاه پرداخت رخ داده است';
407
408
        return $messages[$statusCode] ?? $unknown;
409
    }
410
}
411