Sandbox   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 229
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 20
eloc 93
c 2
b 0
f 1
dl 0
loc 229
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getPurchaseUrl() 0 3 1
A getVerificationUrl() 0 3 1
A getPaymentUrl() 0 3 1
A __construct() 0 5 1
B purchase() 0 44 6
A pay() 0 8 1
A translateStatus() 0 28 2
A createReceipt() 0 3 1
B verify() 0 43 6
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\Zarinpal\Strategies;
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 Sandbox extends Driver
16
{
17
    protected $client;
18
    
19
    /**
20
     * Invoice
21
     *
22
     * @var Invoice
23
     */
24
    protected $invoice;
25
26
    /**
27
     * Driver settings
28
     *
29
     * @var object
30
     */
31
    protected $settings;
32
33
    /**
34
     * Zarinpal constructor.
35
     * Construct the class with the relevant settings.
36
     *
37
     * @param Invoice $invoice
38
     * @param $settings
39
     */
40
    public function __construct(Invoice $invoice, $settings)
41
    {
42
        $this->invoice($invoice);
43
        $this->settings = (object) $settings;
44
        $this->client = new Client();
45
    }
46
47
    /**
48
     * Purchase Invoice.
49
     *
50
     * @return string
51
     *
52
     * @throws PurchaseFailedException
53
     */
54
    public function purchase()
55
    {
56
        $amount = $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 10 : 1); // convert to rial
57
58
        if (!empty($this->invoice->getDetails()['description'])) {
59
            $description = $this->invoice->getDetails()['description'];
60
        } else {
61
            $description = $this->settings->description;
62
        }
63
64
        $data = [
65
            "merchant_id" => $this->settings->merchantId,
66
            "amount" => $amount,
67
            "currency" => 'IRR',
68
            "callback_url" => $this->settings->callbackUrl,
69
            "description" => $description,
70
            'AdditionalData' => $this->invoice->getDetails()
71
        ];
72
73
        $response = $this
74
            ->client
75
            ->request(
76
                'POST',
77
                $this->getPurchaseUrl(),
78
                [
79
                    "json" => $data,
80
                    "headers" => [
81
                        'Content-Type' => 'application/json',
82
                    ],
83
                    "http_errors" => false,
84
                ]
85
            );
86
87
        $result = json_decode($response->getBody()->getContents(), true);
88
89
        if (!empty($result['errors']) || empty($result['data']) || $result['data']['code'] != 100) {
90
            $bodyResponse = $result['errors']['code'];
91
            throw new PurchaseFailedException($this->translateStatus($bodyResponse), $bodyResponse);
92
        }
93
94
        $this->invoice->transactionId($result['data']["authority"]);
95
96
        // return the transaction's id
97
        return $this->invoice->getTransactionId();
98
    }
99
100
    /**
101
     * Pay the Invoice
102
     *
103
     * @return RedirectionForm
104
     */
105
    public function pay() : RedirectionForm
106
    {
107
        $transactionId = $this->invoice->getTransactionId();
108
        $paymentUrl = $this->getPaymentUrl();
109
110
        $payUrl = $paymentUrl.$transactionId;
111
112
        return $this->redirectWithForm($payUrl, [], 'GET');
113
    }
114
115
    /**
116
     * Verify payment
117
     *
118
     * @return ReceiptInterface
119
     *
120
     * @throws InvalidPaymentException
121
     */
122
    public function verify() : ReceiptInterface
123
    {
124
        $authority = $this->invoice->getTransactionId() ?? Request::input('Authority');
125
        $data = [
126
            "merchant_id" => $this->settings->merchantId,
127
            "authority" => $authority,
128
            "amount" => $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 10 : 1), // convert to rial
129
        ];
130
131
        $response = $this->client->request(
132
            'POST',
133
            $this->getVerificationUrl(),
134
            [
135
                'json' => $data,
136
                "headers" => [
137
                    'Content-Type' => 'application/json',
138
                ],
139
                "http_errors" => false,
140
            ]
141
        );
142
143
        $result = json_decode($response->getBody()->getContents(), true);
144
145
        if (empty($result['data']) || !isset($result['data']['ref_id']) || ($result['data']['code'] != 100 && $result['data']['code'] != 101)) {
146
            $bodyResponse = $result['errors']['code'];
147
            throw new InvalidPaymentException($this->translateStatus($bodyResponse), $bodyResponse);
148
        }
149
150
        $refId = $result['data']['ref_id'];
151
152
        $receipt =  $this->createReceipt($refId);
153
        $receipt->detail([
154
            'code' => $result['data']['code'],
155
            'message' => $result['data']['message'] ?? null,
156
            'card_hash' => $result['data']['card_hash'] ?? null,
157
            'card_pan' => $result['data']['card_pan'] ?? null,
158
            'ref_id' => $refId,
159
            'fee_type' => $result['data']['fee_type'] ?? null,
160
            'fee' => $result['data']['fee'] ?? null,
161
            'order_id' => $result['data']['order_id'] ?? null,
162
        ]);
163
164
        return $receipt;
165
    }
166
167
    /**
168
     * Generate the payment's receipt
169
     *
170
     * @param $referenceId
171
     *
172
     * @return Receipt
173
     */
174
    public function createReceipt($referenceId)
175
    {
176
        return new Receipt('zarinpal', $referenceId);
177
    }
178
179
    /**
180
     * Retrieve purchase url
181
     *
182
     * @return string
183
     */
184
    protected function getPurchaseUrl() : string
185
    {
186
        return $this->settings->sandboxApiPurchaseUrl;
187
    }
188
189
    /**
190
     * Retrieve Payment url
191
     *
192
     * @return string
193
     */
194
    protected function getPaymentUrl() : string
195
    {
196
        return $this->settings->sandboxApiPaymentUrl;
197
    }
198
199
    /**
200
     * Retrieve verification url
201
     *
202
     * @return string
203
     */
204
    protected function getVerificationUrl() : string
205
    {
206
        return $this->settings->sandboxApiVerificationUrl;
207
    }
208
209
    /**
210
     * Convert status to a readable message.
211
     *
212
     * @param $status
213
     *
214
     * @return mixed|string
215
     */
216
    private function translateStatus($status)
217
    {
218
        $translations = [
219
            '100' => 'تراکنش با موفقیت انجام گردید',
220
            '101' => 'عمليات پرداخت موفق بوده و قبلا عملیات وریفای تراكنش انجام شده است',
221
            '-9' => 'خطای اعتبار سنجی',
222
            '-10' => 'ای پی و يا مرچنت كد پذيرنده صحيح نمی باشد',
223
            '-11' => 'مرچنت کد فعال نیست لطفا با تیم پشتیبانی ما تماس بگیرید',
224
            '-12' => 'تلاش بیش از حد در یک بازه زمانی کوتاه',
225
            '-15' => 'ترمینال شما به حالت تعلیق در آمده با تیم پشتیبانی تماس بگیرید',
226
            '-16' => 'سطح تاييد پذيرنده پايين تر از سطح نقره ای می باشد',
227
            '-30' => 'اجازه دسترسی به تسویه اشتراکی شناور ندارید',
228
            '-31' => 'حساب بانکی تسویه را به پنل اضافه کنید مقادیر وارد شده برای تسهیم صحيح نمی باشد',
229
            '-32' => 'مقادیر وارد شده برای تسهیم صحيح نمی باشد',
230
            '-33' => 'درصد های وارد شده صحيح نمی باشد',
231
            '-34' => 'مبلغ از کل تراکنش بیشتر است',
232
            '-35' => 'تعداد افراد دریافت کننده تسهیم بیش از حد مجاز است',
233
            '-40' => 'پارامترهای اضافی نامعتبر، expire_in معتبر نیست',
234
            '-50' => 'مبلغ پرداخت شده با مقدار مبلغ در وریفای متفاوت است',
235
            '-51' => 'پرداخت ناموفق',
236
            '-52' => 'خطای غیر منتظره با پشتیبانی تماس بگیرید',
237
            '-53' => 'اتوریتی برای این مرچنت کد نیست',
238
            '-54' => 'اتوریتی نامعتبر است',
239
        ];
240
241
        $unknownError = 'خطای ناشناخته رخ داده است. در صورت کسر مبلغ از حساب حداکثر پس از 72 ساعت به حسابتان برمیگردد';
242
243
        return array_key_exists($status, $translations) ? $translations[$status] : $unknownError;
244
    }
245
}
246