Sadad::verify()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 52
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 3 Features 2
Metric Value
cc 3
eloc 29
c 6
b 3
f 2
nc 3
nop 0
dl 0
loc 52
rs 9.456

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\Sadad;
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
use DateTimeZone;
15
use DateTime;
16
17
class Sadad extends Driver
18
{
19
    /**
20
     * Sadad Client.
21
     *
22
     * @var object
23
     */
24
    protected $client;
25
26
    /**
27
     * Invoice
28
     *
29
     * @var Invoice
30
     */
31
    protected $invoice;
32
33
    /**
34
     * Driver settings
35
     *
36
     * @var object
37
     */
38
    protected $settings;
39
40
    /**
41
     * Sadad constructor.
42
     * Construct the class with the relevant settings.
43
     *
44
     * @param Invoice $invoice
45
     * @param $settings
46
     */
47
    public function __construct(Invoice $invoice, $settings)
48
    {
49
        $this->invoice($invoice);
50
        $this->settings = (object) $settings;
51
        $this->client = new Client();
52
    }
53
54
    /**
55
     * Purchase Invoice.
56
     *
57
     * @return string
58
     *
59
     * @throws PurchaseFailedException
60
     * @throws \GuzzleHttp\Exception\GuzzleException
61
     */
62
    public function purchase()
63
    {
64
        $terminalId = $this->settings->terminalId;
65
        $orderId = crc32($this->invoice->getUuid());
66
        $amount = $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 10 : 1); // convert to rial
67
        $key = $this->settings->key;
68
69
        $signData = $this->encrypt_pkcs7("$terminalId;$orderId;$amount", $key);
70
        $iranTime = new DateTime('now', new DateTimeZone('Asia/Tehran'));
71
72
        //set Description for payment
73
        if (!empty($this->invoice->getDetails()['description'])) {
74
            $description = $this->invoice->getDetails()['description'];
75
        } else {
76
            $description = $this->settings->description;
77
        }
78
79
        //set MobileNo for get user cards
80
        if (!empty($this->invoice->getDetails()['mobile'])) {
81
            $mobile = $this->invoice->getDetails()['mobile'];
82
        } else {
83
            $mobile = "";
84
        }
85
86
        $data = [
87
            'MerchantId' => $this->settings->merchantId,
88
            'ReturnUrl' => $this->settings->callbackUrl,
89
            'LocalDateTime' => $iranTime->format("m/d/Y g:i:s a"),
90
            'SignData' => $signData,
91
            'TerminalId' => $terminalId,
92
            'Amount' => $amount,
93
            'OrderId' => $orderId,
94
            'additionalData' => $description,
95
            'UserId' => $mobile,
96
        ];
97
98
        $mode = $this->getMode();
99
100
        if ($mode == 'paymentbyidentity') {
101
            //set PaymentIdentity for payment
102
            if (!empty($this->invoice->getDetails()['payment_identity'])) {
103
                $data['PaymentIdentity'] = $this->invoice->getDetails()['payment_identity'];
104
            } else {
105
                $data['PaymentIdentity'] = $this->settings->PaymentIdentity;
106
            }
107
        } elseif ($mode == 'paymentbymultiidentity') {
108
            //set MultiIdentityData for payment
109
            if (!empty($this->invoice->getDetails()['multi_identity_rows'])) {
110
                $multiIdentityRows = $this->invoice->getDetails()['multi_identity_rows'];
111
            } else {
112
                $multiIdentityRows = $this->settings->MultiIdentityRows;
113
            }
114
115
            // convert to rial
116
            if ($this->settings->currency == 'T') {
117
                $multiIdentityRows = array_map(function ($item) {
118
                    $item['Amount'] = $item['Amount'] * 10;
119
                    return $item;
120
                }, $multiIdentityRows);
121
            }
122
123
            $data['MultiIdentityData'] = ['MultiIdentityRows' => $multiIdentityRows];
124
        }
125
126
        $response = $this
127
            ->client
128
            ->request(
129
                'POST',
130
                $this->getPaymentUrl(),
131
                [
132
                    "json" => $data,
133
                    "headers" => [
134
                        'Content-Type' => 'application/json',
135
                        'User-Agent' => '',
136
                    ],
137
                    "http_errors" => false,
138
                ]
139
            );
140
141
        $body = @json_decode($response->getBody()->getContents());
142
143
        if (empty($body)) {
144
            throw new PurchaseFailedException('دسترسی به صفحه مورد نظر امکان پذیر نمی باشد.');
145
        } elseif ($body->ResCode != 0) {
146
            throw new PurchaseFailedException($body->Description);
147
        }
148
149
        $this->invoice->transactionId($body->Token);
150
151
        // return the transaction's id
152
        return $this->invoice->getTransactionId();
153
    }
154
155
    /**
156
     * Pay the Invoice
157
     *
158
     * @return RedirectionForm
159
     */
160
    public function pay() : RedirectionForm
161
    {
162
        $token = $this->invoice->getTransactionId();
163
        $payUrl = $this->getPurchaseUrl();
164
165
        return $this->redirectWithForm($payUrl, ['Token' => $token], 'GET');
166
    }
167
168
    /**
169
     * Verify payment
170
     *
171
     * @return ReceiptInterface
172
     *
173
     * @throws InvalidPaymentException
174
     * @throws \GuzzleHttp\Exception\GuzzleException
175
     */
176
    public function verify() : ReceiptInterface
177
    {
178
        $key = $this->settings->key;
179
        $token = $this->invoice->getTransactionId() ?? Request::input('token');
180
        $resCode = Request::input('ResCode');
181
182
        if ($resCode != 0) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $resCode of type mixed|null to 0; this is ambiguous as not only 0 == 0 is true, but null == 0 is true, too. Consider using a strict comparison ===.
Loading history...
183
            throw new InvalidPaymentException($this->translateStatus($resCode), $resCode);
184
        }
185
186
        $data = array(
187
            'Token' => $token,
188
            'SignData' => $this->encrypt_pkcs7($token, $key)
189
        );
190
191
        $response = $this
192
            ->client
193
            ->request(
194
                'POST',
195
                $this->settings->apiVerificationUrl,
196
                [
197
                    "json" => $data,
198
                    "headers" => [
199
                        'Content-Type' => 'application/json',
200
                        'User-Agent' => '',
201
                    ],
202
                    "http_errors" => false,
203
                ]
204
            );
205
206
        $body = json_decode($response->getBody()->getContents());
207
208
        $bodyResponse = $body->ResCode;
209
        if ($bodyResponse != 0) {
210
            throw new InvalidPaymentException($this->translateStatus($bodyResponse), $bodyResponse);
211
        }
212
213
        /**
214
         * شماره سفارش : $orderId = Request::input('OrderId')
215
         * شماره پیگیری : $body->SystemTraceNo
216
         * شماره مرجع : $body->RetrievalRefNo
217
         */
218
219
        $receipt = $this->createReceipt($body->SystemTraceNo);
220
        $receipt->detail([
221
            'orderId' => $body->OrderId,
222
            'traceNo' => $body->SystemTraceNo,
223
            'referenceNo' => $body->RetrivalRefNo,
224
            'description' => $body->Description,
225
        ]);
226
227
        return $receipt;
228
    }
229
230
    /**
231
     * Generate the payment's receipt
232
     *
233
     * @param $referenceId
234
     *
235
     * @return Receipt
236
     */
237
    protected function createReceipt($referenceId)
238
    {
239
        $receipt = new Receipt('sadad', $referenceId);
240
241
        return $receipt;
242
    }
243
244
    /**
245
     * Create sign data(Tripledes(ECB,PKCS7))
246
     *
247
     * @param $str
248
     * @param $key
249
     *
250
     * @return string
251
     */
252
    protected function encrypt_pkcs7($str, $key)
253
    {
254
        $key = base64_decode($key);
255
        $ciphertext = OpenSSL_encrypt($str, "DES-EDE3", $key, OPENSSL_RAW_DATA);
256
257
        return base64_encode($ciphertext);
258
    }
259
260
    /**
261
     * Retrieve payment mode.
262
     *
263
     * @return string
264
     */
265
    protected function getMode() : string
266
    {
267
        return strtolower($this->settings->mode);
268
    }
269
270
271
    /**
272
     * Retrieve purchase url
273
     *
274
     * @return string
275
     */
276
    protected function getPurchaseUrl() : string
277
    {
278
        return $this->settings->apiPurchaseUrl;
279
    }
280
281
    /**
282
     * Retrieve Payment url
283
     *
284
     * @return string
285
     */
286
    protected function getPaymentUrl() : string
287
    {
288
        $mode = $this->getMode();
289
290
        switch ($mode) {
291
            case 'paymentbyidentity':
292
                $url = $this->settings->apiPaymentByIdentityUrl;
293
                break;
294
            case 'paymentbymultiidentity':
295
                $url = $this->settings->apiPaymentByMultiIdentityUrl;
296
                break;
297
            default: // default: normal
298
                $url = $this->settings->apiPaymentUrl;
299
                break;
300
        }
301
302
        return $url;
303
    }
304
305
    /**
306
     * Convert status to a readable message.
307
     *
308
     * @param $status
309
     *
310
     * @return mixed|string
311
     */
312
    private function translateStatus($status)
313
    {
314
        $translations = [
315
            '0' => 'تراکنش با موفقیت انجام شد',
316
            '3' => 'پذيرنده کارت فعال نیست لطفا با بخش امور پذيرندگان، تماس حاصل فرمائید',
317
            '23' => 'پذيرنده کارت نا معتبر لطفا با بخش امور پذيرندگان، تماس حاصل فرمائید',
318
            '58' => 'انجام تراکنش مربوطه توسط پايانه ی انجام دهنده مجاز نمی باشد',
319
            '61' => 'مبلغ تراکنش از حد مجاز بالاتر است',
320
            '101' => 'مهلت ارسال تراکنش به پايان رسیده است',
321
            '1000' => 'ترتیب پارامترهای ارسالی اشتباه می باشد',
322
            '1001' => 'پارامترهای پرداخت اشتباه می باشد',
323
            '1002' => 'خطا در سیستم- تراکنش ناموفق',
324
            '1003' => 'IP پذيرنده اشتباه است',
325
            '1004' => 'شماره پذيرنده اشتباه است',
326
            '1005' => 'خطای دسترسی:لطفا بعدا تلاش فرمايید',
327
            '1006' => 'خطا در سیستم',
328
            '1011' => 'درخواست تکراری- شماره سفارش تکراری می باشد',
329
            '1012' => 'اطلاعات پذيرنده صحیح نیست، يکی از موارد تاريخ،زمان يا کلید تراکنش اشتباه است',
330
            '1015' => 'پاسخ خطای نامشخص از سمت مرکز',
331
            '1017' => 'مبلغ درخواستی شما جهت پرداخت از حد مجاز تعريف شده برای اين پذيرنده بیشتر است',
332
            '1018' => 'اشکال در تاريخ و زمان سیستم. لطفا تاريخ و زمان سرور خود را با بانک هماهنگ نمايید',
333
            '1019' => 'امکان پرداخت از طريق سیستم شتاب برای اين پذيرنده امکان پذير نیست',
334
            '1020' => 'پذيرنده غیرفعال شده است',
335
            '1023' => 'آدرس بازگشت پذيرنده نامعتبر است',
336
            '1024' => 'مهر زمانی پذيرنده نامعتبر است',
337
            '1025' => 'امضا تراکنش نامعتبر است',
338
            '1026' => 'شماره سفارش تراکنش نامعتبر است',
339
            '1027' => 'شماره پذيرنده نامعتبر است',
340
            '1028' => 'شماره ترمینال پذيرنده نامعتبر است',
341
            '1029' => 'آدرس IP پرداخت در محدوده آدرس های معتبر اعلام شده توسط پذيرنده نیست',
342
            '1030' => 'آدرس Domain پرداخت در محدوده آدرس های معتبر اعلام شده توسط پذیرنده نیست',
343
            '1031' => 'مهلت زمانی شما جهت پرداخت به پايان رسیده است.لطفا مجددا سعی بفرمایید',
344
            '1032' => 'پرداخت با اين کارت , برای پذيرنده مورد نظر شما امکان پذير نیست',
345
            '1033' => 'به علت مشکل در سايت پذيرنده, پرداخت برای اين پذيرنده غیرفعال شده است',
346
            '1036' => 'اطلاعات اضافی ارسال نشده يا دارای اشکال است',
347
            '1037' => 'شماره پذيرنده يا شماره ترمینال پذيرنده صحیح نمیباشد',
348
            '1053' => 'خطا: درخواست معتبر، از سمت پذيرنده صورت نگرفته است لطفا اطلاعات پذيرنده خود را چک کنید',
349
            '1055' => 'مقدار غیرمجاز در ورود اطلاعات',
350
            '1056' => 'سیستم موقتا قطع میباشد.لطفا بعدا تلاش فرمايید',
351
            '1058' => 'سرويس پرداخت اينترنتی خارج از سرويس می باشد.لطفا بعدا سعی بفرمایید',
352
            '1061' => 'اشکال در تولید کد يکتا. لطفا مرورگر خود را بسته و با اجرای مجدد عملیات پرداخت را انجام دهید',
353
            '1064' => 'لطفا مجددا سعی بفرمايید',
354
            '1065' => 'ارتباط ناموفق .لطفا چند لحظه ديگر مجددا سعی کنید',
355
            '1066' => 'سیستم سرويس دهی پرداخت موقتا غیر فعال شده است',
356
            '1068' => 'با عرض پوزش به علت بروزرسانی , سیستم موقتا قطع میباشد',
357
            '1072' => 'خطا در پردازش پارامترهای اختیاری پذيرنده',
358
            '1101' => 'مبلغ تراکنش نامعتبر است',
359
            '1103' => 'توکن ارسالی نامعتبر است',
360
            '1104' => 'اطلاعات تسهیم صحیح نیست',
361
            '1105' => 'تراکنش بازگشت داده شده است(مهلت زمانی به پايان رسیده است)'
362
        ];
363
364
        $unknownError = 'خطای ناشناخته رخ داده است. در صورت کسر مبلغ از حساب حداکثر پس از 72 ساعت به حسابتان برمیگردد';
365
366
        return array_key_exists($status, $translations) ? $translations[$status] : $unknownError;
367
    }
368
}
369