Passed
Pull Request — master (#247)
by
unknown
02:52
created

Snapppay::purchase()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 68
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 6
eloc 41
c 1
b 0
f 1
nc 16
nop 0
dl 0
loc 68
rs 8.6417

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
4
namespace Shetabit\Multipay\Drivers\Snapppay;
5
6
use GuzzleHttp\Client;
7
use GuzzleHttp\Exception\GuzzleException;
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 Snapppay extends Driver
19
{
20
    /**
21
     * Digipay Client.
22
     *
23
     * @var Client
24
     */
25
    protected $client;
26
27
    /**
28
     * Invoice
29
     *
30
     * @var Invoice
31
     */
32
    protected $invoice;
33
34
    /**
35
     * Driver settings
36
     *
37
     * @var object
38
     */
39
    protected $settings;
40
    /**
41
     * snapppay Oauth Token
42
     *
43
     * @var string
44
     */
45
    protected $oauthToken;
46
47
    /**
48
     * Snapppay payment url
49
     *
50
     * @var string
51
     */
52
    protected $paymentUrl;
53
    protected $paymentToken;
54
55
    /**
56
     * Snapppay constructor.
57
     * Construct the class with the relevant settings.
58
     *
59
     * @param Invoice $invoice
60
     * @param $settings
61
     */
62
    public function __construct(Invoice $invoice, $settings)
63
    {
64
65
        $this->invoice($invoice);
66
        $this->settings = (object)$settings;
67
        $this->client = new Client();
68
        $this->oauthToken = $this->oauth();
69
    }
70
71
    /**
72
     * @throws PurchaseFailedException
73
     */
74
    public function purchase(): string
75
    {
76
77
78
        $phone = $this->invoice->getDetail('phone') ?? $this->invoice->getDetail('mobile');
79
        $phoneNumber = preg_replace('/\D/', '', $phone);
80
81
        // Check if the number starts with '0' and is 11 digits long
82
        if (strlen($phoneNumber) === 11 && $phoneNumber[0] === '0') {
83
            // Replace the leading '0' with '+98'
84
            $phoneNumber = '+98' . substr($phoneNumber, 1);
85
        }
86
        $data = [
87
            "amount" => $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 10 : 1),
88
            "cartList" => [
89
                [
90
                    "cartId" => 1,
91
                    "cartItems" => [
92
                        [
93
                            "amount" => 0,
94
                            "category" => "string",
95
                            "count" => 1,
96
                            "id" => 0,
97
                            "name" => "string",
98
                            "commissionType" => 0
99
                        ]
100
                    ],
101
                    "isShipmentIncluded" => false,
102
                    "isTaxIncluded" => false,
103
                    "shippingAmount" => 0,
104
                    "taxAmount" => 0,
105
                    "totalAmount" => $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 10 : 1),
106
                ]
107
            ],
108
109
110
            "discountAmount" => 0,
111
            "externalSourceAmount" => 0,
112
            "mobile" => $phoneNumber,
113
            "paymentMethodTypeDto" => "INSTALLMENT",
114
            "returnURL" => $this->settings->callbackUrl,
115
            "transactionId" => $this->invoice->getUuid()
116
        ];
117
118
        $response = $this->client->request(
119
            'POST',
120
            $this->settings->apiPurchaseUrl,
121
            [
122
                RequestOptions::BODY => json_encode($data),
123
                RequestOptions::HEADERS => [
124
                    'Content-Type' => 'application/json',
125
                    'Authorization' => 'Bearer ' . $this->oauthToken,
126
                ],
127
                RequestOptions::HTTP_ERRORS => false,
128
            ]
129
        );
130
131
        $body = json_decode($response->getBody()->getContents(), true);
132
        if ($response->getStatusCode() != 200) {
133
            // error has happened
134
            $message = $body['result']['message'] ?? 'خطا در هنگام درخواست برای پرداخت رخ داده است.';
135
            throw new PurchaseFailedException($message);
136
        }
137
        $this->invoice->transactionId($body['response']['paymentToken']);
138
        $this->setPaymentUrl($body['response']['paymentPageUrl']);
139
140
        // return the transaction's id
141
        return $this->invoice->getTransactionId();
142
    }
143
144
    public function pay(): RedirectionForm
145
    {
146
        parse_str(parse_url($this->getPaymentUrl(), PHP_URL_QUERY), $formData);
147
        return $this->redirectWithForm($this->getPaymentUrl(), $formData, 'GET');
148
    }
149
150
    /**
151
     * @throws InvalidPaymentException
152
     */
153
    public function verify(): ReceiptInterface
154
    {
155
156
157
        $response = $this->client->request(
158
            'POST',
159
            $this->settings->apiVerificationUrl,
160
            [
161
                RequestOptions::BODY => json_encode(['paymentToken' => $this->invoice->getTransactionId()]),
162
                RequestOptions::HEADERS => [
163
                    'Content-Type' => 'application/json',
164
                    'Authorization' => 'Bearer ' . $this->oauthToken,
165
                ],
166
                RequestOptions::HTTP_ERRORS => false,
167
            ]
168
        );
169
170
171
        $body = json_decode($response->getBody()->getContents(), true);
172
        if ($response->getStatusCode() != 200) {
173
            $message = $body['result']['message'] ?? 'تراکنش تایید نشد';
174
            throw new InvalidPaymentException($message, (int)$response->getStatusCode());
175
        }
176
177
        return (new Receipt('snapppay', $body["response"]['transactionId']))->detail($body);
178
    }
179
180
    /**
181
     * @throws PurchaseFailedException
182
     */
183
    protected function oauth()
184
    {
185
186
        $response = $this
187
            ->client
188
            ->request(
189
                'POST',
190
                $this->settings->apiOauthUrl,
191
                [
192
                    RequestOptions::HEADERS => [
193
                        'Authorization' => 'Basic ' . base64_encode("{$this->settings->client_id}:{$this->settings->client_secret}"),
194
                    ],
195
                    RequestOptions::MULTIPART => [
196
                        [
197
                            "name" => "username",
198
                            "contents" => $this->settings->username,
199
                        ],
200
                        [
201
                            "name" => "password",
202
                            "contents" => $this->settings->password,
203
                        ],
204
                        [
205
                            "name" => "grant_type",
206
                            "contents" => 'password',
207
                        ],
208
                    ],
209
                    RequestOptions::HTTP_ERRORS => false,
210
                ]
211
            );
212
213
214
        if ($response->getStatusCode() != 200) {
215
            if ($response->getStatusCode() == 401) {
216
                throw new PurchaseFailedException("خطا نام کاربری یا رمز عبور شما اشتباه می باشد.");
217
            } else {
218
                throw new PurchaseFailedException("خطا در هنگام احراز هویت.");
219
            }
220
        }
221
222
223
        $body = json_decode($response->getBody()->getContents(), true);
224
        $this->oauthToken = $body['access_token'];
225
        return $body['access_token'];
226
    }
227
228
    /**
229
     * @return string
230
     */
231
    public function getPaymentUrl(): string
232
    {
233
        return $this->paymentUrl;
234
    }
235
236
    public function getPaymentToken(): string
237
    {
238
        return $this->paymentToken;
239
    }
240
241
    /**
242
     * @param string $paymentUrl
243
     */
244
    public function setPaymentUrl(string $paymentUrl): void
245
    {
246
        $this->paymentUrl = $paymentUrl;
247
    }
248
249
    public function setPaymentToken(string $paymentToken): void
250
    {
251
        $this->paymentToken = $paymentToken;
252
    }
253
}
254