Passed
Pull Request — master (#231)
by
unknown
02:41
created

Digipay::deliver()   B

Complexity

Conditions 11
Paths 10

Size

Total Lines 65
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
cc 11
eloc 37
c 2
b 1
f 1
nc 10
nop 0
dl 0
loc 65
rs 7.3166

How to fix   Long Method    Complexity   

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
4
namespace Shetabit\Multipay\Drivers\Digipay;
5
6
use DateTime;
7
use GuzzleHttp\Client;
8
use GuzzleHttp\RequestOptions;
9
use Shetabit\Multipay\Abstracts\Driver;
10
use Shetabit\Multipay\Contracts\ReceiptInterface;
11
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
12
use Shetabit\Multipay\Exceptions\PurchaseFailedException;
13
use Shetabit\Multipay\Invoice;
14
use Shetabit\Multipay\Receipt;
15
use Shetabit\Multipay\RedirectionForm;
16
use Shetabit\Multipay\Request;
17
18
class Digipay extends Driver
19
{
20
    const VERSION      = '2022-02-02';
21
    const OAUTH_URL    = '/digipay/api/oauth/token';
22
    const PURCHASE_URL = '/digipay/api/tickets/business';
23
    const VERIFY_URL   = '/digipay/api/purchases/verify/';
24
    const REVERSE_URL  = '/digipay/api/reverse';
25
    const DELIVER_URL  = '/digipay/api/purchases/deliver';
26
27
    /**
28
     * Digipay Client.
29
     *
30
     * @var Client
31
     */
32
    protected $client;
33
34
    /**
35
     * Invoice
36
     *
37
     * @var Invoice
38
     */
39
    protected $invoice;
40
41
    /**
42
     * Driver settings
43
     *
44
     * @var object
45
     */
46
    protected $settings;
47
    /**
48
     * Digipay Oauth Token
49
     *
50
     * @var string
51
     */
52
    protected $oauthToken;
53
54
    /**
55
     * Digipay payment url
56
     *
57
     * @var string
58
     */
59
    protected $paymentUrl;
60
61
    /**
62
     * Digipay constructor.
63
     * Construct the class with the relevant settings.
64
     *
65
     * @param Invoice $invoice
66
     * @param $settings
67
     */
68
    public function __construct(Invoice $invoice, $settings)
69
    {
70
        $this->invoice($invoice);
71
        $this->settings   = (object) $settings;
72
        $this->client     = new Client();
73
        $this->oauthToken = $this->oauth();
74
    }
75
76
    /**
77
     * @throws PurchaseFailedException
78
     */
79
    public function purchase(): string
80
    {
81
        $phone = $this->invoice->getDetail('phone')
82
            ?? $this->invoice->getDetail('cellphone')
83
            ?? $this->invoice->getDetail('mobile');
84
85
        /**
86
         * @see https://docs.mydigipay.com/upg.html#_request_fields_2
87
         */
88
        $data = [
89
            'amount'      => $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 10 : 1),
90
            'cellNumber'  => $phone,
91
            'providerId'  => $this->invoice->getUuid(),
92
            'callbackUrl' => $this->settings->callbackUrl,
93
        ];
94
95
        if (!is_null($basketDetailsDto = $this->invoice->getDetail('basketDetailsDto'))) {
96
            $data['basketDetailsDto'] = $basketDetailsDto;
97
        }
98
99
        if (!is_null($preferredGateway = $this->invoice->getDetail('preferredGateway'))) {
100
            $data['preferredGateway'] = $preferredGateway;
101
        }
102
103
        if (!is_null($splitDetailsList = $this->invoice->getDetail('splitDetailsList'))) {
104
            $data['splitDetailsList'] = $splitDetailsList;
105
        }
106
107
        /**
108
         * @see https://docs.mydigipay.com/upg.html#_query_parameters_2
109
         */
110
        $digipayType = $this->invoice->getDetail('digipayType') ?? 11;
111
112
        $response = $this
113
            ->client
114
            ->request(
115
                'POST',
116
                $this->settings->apiPaymentUrl . self::PURCHASE_URL,
117
                [
118
                    RequestOptions::BODY  => json_encode($data),
119
                    RequestOptions::QUERY  => ['type' => $digipayType],
120
                    RequestOptions::HEADERS   => [
121
                        'Agent' => $this->invoice->getDetail('agent') ?? 'WEB',
122
                        'Content-Type'  => 'application/json',
123
                        'Authorization' => 'Bearer ' . $this->oauthToken,
124
                        'Digipay-Version' => self::VERSION,
125
                    ],
126
                    RequestOptions::HTTP_ERRORS => false,
127
                ]
128
            );
129
130
        $body = json_decode($response->getBody()->getContents(), true);
131
132
        if ($response->getStatusCode() != 200) {
133
            // error has happened
134
            $message = $body['result']['message'] ?? 'خطا در هنگام درخواست برای پرداخت رخ داده است.';
135
            throw new PurchaseFailedException($message);
136
        }
137
138
        $this->invoice->transactionId($body['ticket']);
139
        $this->setPaymentUrl($body['redirectUrl']);
140
141
        // return the transaction's id
142
        return $this->invoice->getTransactionId();
143
    }
144
145
    public function pay(): RedirectionForm
146
    {
147
        return $this->redirectWithForm($this->getPaymentUrl(), [], 'GET');
148
    }
149
150
    /**
151
     * @throws InvalidPaymentException
152
     */
153
    public function verify(): ReceiptInterface
154
    {
155
        /**
156
         * @see https://docs.mydigipay.com/upg.html#ticket_type
157
         */
158
        $digipayTicketType = Request::input('type');
159
        $tracingId = Request::input('trackingCode');
160
161
        $response = $this->client->request(
162
            'POST',
163
            $this->settings->apiPaymentUrl . self::VERIFY_URL . $tracingId,
164
            [
165
                RequestOptions::QUERY      => ['type' => $digipayTicketType],
166
                RequestOptions::HEADERS    => [
167
                    "Accept"        => "application/json",
168
                    "Authorization" => "Bearer " . $this->oauthToken,
169
                ],
170
                RequestOptions::HTTP_ERRORS => false,
171
            ]
172
        );
173
174
        $body = json_decode($response->getBody()->getContents(), true);
175
176
        if ($response->getStatusCode() != 200) {
177
            $message = $body['result']['message'] ?? 'تراکنش تایید نشد';
178
            throw new InvalidPaymentException($message, (int) $response->getStatusCode());
179
        }
180
181
        return (new Receipt('digipay', $body["trackingCode"]))->detail($body);
182
    }
183
184
    /**
185
     * @throws PurchaseFailedException
186
     */
187
    protected function oauth()
188
    {
189
        $response = $this
190
            ->client
191
            ->request(
192
                'POST',
193
                $this->settings->apiPaymentUrl . self::OAUTH_URL,
194
                [
195
                    RequestOptions::HEADERS   => [
196
                        'Authorization' => 'Basic ' . base64_encode("{$this->settings->client_id}:{$this->settings->client_secret}"),
197
                    ],
198
                    RequestOptions::MULTIPART   => [
199
                        [
200
                            "name"     => "username",
201
                            "contents" => $this->settings->username,
202
                        ],
203
                        [
204
                            "name"     => "password",
205
                            "contents" => $this->settings->password,
206
                        ],
207
                        [
208
                            "name"     => "grant_type",
209
                            "contents" => 'password',
210
                        ],
211
                    ],
212
                    RequestOptions::HTTP_ERRORS => false,
213
                ]
214
            );
215
216
        if ($response->getStatusCode() != 200) {
217
            if ($response->getStatusCode() == 401) {
218
                throw new PurchaseFailedException("خطا نام کاربری یا رمز عبور شما اشتباه می باشد.");
219
            } else {
220
                throw new PurchaseFailedException("خطا در هنگام احراز هویت.");
221
            }
222
        }
223
224
        $body = json_decode($response->getBody()->getContents(), true);
225
226
        $this->oauthToken = $body['access_token'];
227
        return $body['access_token'];
228
    }
229
230
    /**
231
     * @see https://docs.mydigipay.com/upg.html#_purchase_reverse
232
     * @throws PurchaseFailedException
233
     */
234
    public function reverse()
235
    {
236
        if (is_null($digipayTicketType = $this->invoice->getDetail('type'))) {
237
            throw new PurchaseFailedException('"type" is required for this method.');
238
        }
239
240
        if (is_null($trackingCode = $this->invoice->getDetail('trackingCode'))) {
241
            throw new PurchaseFailedException('"trackingCode" is required for this method.');
242
        }
243
244
        $data = [
245
            'trackingCode' => $trackingCode,
246
            'providerId'    => $this->invoice->getTransactionId() ?? $this->invoice->getDetail('providerId') ?? $this->invoice->getUuid(),
247
        ];
248
249
        $response = $this
250
            ->client
251
            ->request(
252
                'POST',
253
                $this->settings->apiPaymentUrl . self::REVERSE_URL,
254
                [
255
                    RequestOptions::BODY        => json_encode($data),
256
                    RequestOptions::QUERY       => ['type' => $digipayTicketType],
257
                    RequestOptions::HEADERS     => [
258
                        'Content-Type'    => 'application/json;charset=UTF-8',
259
                        'Authorization'   => 'Bearer ' . $this->oauthToken,
260
                    ],
261
                    RequestOptions::HTTP_ERRORS => false,
262
                ]
263
            );
264
265
        $body = json_decode($response->getBody()->getContents(), true);
266
267
        if ($response->getStatusCode() != 200 || $body['result']['code'] != 0) {
268
            $message = $body['result']['message'] ?? 'خطا در هنگام درخواست برای برگشت وجه رخ داده است.';
269
            throw new InvalidPaymentException($message, (int) $response->getStatusCode());
270
        }
271
272
        return $body;
273
    }
274
275
    /**
276
     * @see https://docs.mydigipay.com/upg.html#_purchase_delivery
277
     * @throws PurchaseFailedException
278
     */
279
    public function deliver()
280
    {
281
        if (empty($type = $this->invoice->getDetail('type'))) {
282
            throw new PurchaseFailedException('"type" is required for this method.');
283
        }
284
285
        if (!in_array($type, [5, 13])) {
286
            throw new PurchaseFailedException('This method is not supported for this type.');
287
        }
288
289
        if (empty($invoiceNumber = $this->invoice->getDetail('invoiceNumber'))) {
290
            throw new PurchaseFailedException('"invoiceNumber" is required for this method.');
291
        }
292
293
        if (empty($deliveryDate = $this->invoice->getDetail('deliveryDate'))) {
294
            throw new PurchaseFailedException('"deliveryDate" is required for this method.');
295
        }
296
297
        if (!DateTime::createFromFormat('Y-m-d', $deliveryDate)) {
298
            throw new PurchaseFailedException('"deliveryDate" must be a valid date with format Y-m-d.');
299
        }
300
301
        if (empty($trackingCode = $this->invoice->getDetail('trackingCode'))) {
302
            throw new PurchaseFailedException('"trackingCode" is required for this method.');
303
        }
304
305
        if (empty($products = $this->invoice->getDetail('products'))) {
306
            throw new PurchaseFailedException('"products" is required for this method.');
307
        }
308
309
        if (!is_array($products)) {
0 ignored issues
show
introduced by
The condition is_array($products) is always false.
Loading history...
310
            throw new PurchaseFailedException('"products" must be an array.');
311
        }
312
313
        $data = [
314
            'invoiceNumber' => $invoiceNumber,
315
            'deliveryDate'  => $deliveryDate,
316
            'trackingCode'  => $trackingCode,
317
            'products'      => $products,
318
        ];
319
320
        $response = $this
321
            ->client
322
            ->request(
323
                'POST',
324
                $this->settings->apiPaymentUrl . self::DELIVER_URL,
325
                [
326
                    RequestOptions::BODY        => json_encode($data),
327
                    RequestOptions::QUERY       => ['type' => $type],
328
                    RequestOptions::HEADERS     => [
329
                        'Content-Type'  => 'application/json;charset=UTF-8',
330
                        'Authorization' => 'Bearer ' . $this->oauthToken,
331
                    ],
332
                    RequestOptions::HTTP_ERRORS => false,
333
                ]
334
            );
335
336
        $body = json_decode($response->getBody()->getContents(), true);
337
338
        if ($response->getStatusCode() != 200 || $body['result']['code'] != 0) {
339
            $message = $body['result']['message'] ?? 'خطا در هنگام درخواست برای تحویل کالا رخ داده است.';
340
            throw new InvalidPaymentException($message, (int) $response->getStatusCode());
341
        }
342
343
        return $body;
344
    }
345
346
    /**
347
     * @return string
348
     */
349
    public function getPaymentUrl(): string
350
    {
351
        return $this->paymentUrl;
352
    }
353
354
    /**
355
     * @param string $paymentUrl
356
     */
357
    public function setPaymentUrl(string $paymentUrl): void
358
    {
359
        $this->paymentUrl = $paymentUrl;
360
    }
361
}
362