Passed
Pull Request — master (#148)
by
unknown
08:54
created

Behpardakht::refund()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 34
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 20
c 0
b 0
f 0
nc 4
nop 0
dl 0
loc 34
rs 9.6
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\Behpardakht;
4
5
use Shetabit\Multipay\Abstracts\Driver;
6
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
7
use Shetabit\Multipay\Exceptions\PurchaseFailedException;
8
use Shetabit\Multipay\Contracts\ReceiptInterface;
9
use Shetabit\Multipay\Invoice;
10
use Shetabit\Multipay\Receipt;
11
use Shetabit\Multipay\Request;
12
use Carbon\Carbon;
13
use Shetabit\Multipay\RedirectionForm;
14
15
class Behpardakht extends Driver
16
{
17
    /**
18
     * Invoice
19
     *
20
     * @var Invoice
21
     */
22
    protected $invoice;
23
24
    /**
25
     * Driver settings
26
     *
27
     * @var object
28
     */
29
    protected $settings;
30
31
    /**
32
     * Behpardakht constructor.
33
     * Construct the class with the relevant settings.
34
     *
35
     * @param Invoice $invoice
36
     * @param $settings
37
     */
38
    public function __construct(Invoice $invoice, $settings)
39
    {
40
        $this->invoice($invoice);
41
        $this->settings = (object)$settings;
42
    }
43
44
    /**
45
     * Purchase Invoice.
46
     *
47
     * @return string
48
     *
49
     * @throws PurchaseFailedException
50
     * @throws \SoapFault
51
     */
52
53
    public function purchase()
54
    {
55
        if (isset($_SERVER['SERVER_PROTOCOL']) && $_SERVER['SERVER_PROTOCOL'] == "HTTP/2.0") {
56
            $context = stream_context_create(
57
                [
58
                'ssl' => array(
59
                  'verify_peer'       => false,
60
                  'verify_peer_name'  => false
61
                )]
62
            );
63
64
            $soap = new \SoapClient($this->settings->apiPurchaseUrl, [
65
                'stream_context' => $context
66
            ]);
67
        } else {
68
            $soap = new \SoapClient($this->settings->apiPurchaseUrl);
69
        }
70
71
        $response = $soap->bpPayRequest($this->preparePurchaseData());
72
73
        // fault has happened in bank gateway
74
        if ($response->return == 21) {
75
            throw new PurchaseFailedException('پذیرنده معتبر نیست.', 21);
76
        }
77
78
        $data = explode(',', $response->return);
79
80
        // purchase was not successful
81
        if ($data[0] != "0") {
82
            throw new PurchaseFailedException($this->translateStatus($data[0]), (int)$data[0]);
83
        }
84
85
        $this->invoice->transactionId($data[1]);
86
87
        // return the transaction's id
88
        return $this->invoice->getTransactionId();
89
    }
90
91
    /**
92
     * Pay the Invoice
93
     *
94
     * @return RedirectionForm
95
     */
96
    public function pay(): RedirectionForm
97
    {
98
        $payUrl = $this->settings->apiPaymentUrl;
99
100
        $data = [
101
            'RefId' => $this->invoice->getTransactionId()
102
        ];
103
104
        //set mobileNo for get user cards
105
        if (!empty($this->invoice->getDetails()['mobile'])) {
106
            $data['MobileNo'] = $this->invoice->getDetails()['mobile'];
107
        }
108
109
        return $this->redirectWithForm($payUrl, $data, 'POST');
110
    }
111
112
    /**
113
     * Verify payment
114
     *
115
     * @return mixed|Receipt
116
     *
117
     * @throws InvalidPaymentException
118
     * @throws \SoapFault
119
     */
120
    public function verify(): ReceiptInterface
121
    {
122
        $resCode = Request::input('ResCode');
123
        if ($resCode != '0') {
124
            throw new InvalidPaymentException($this->translateStatus($resCode), $resCode);
125
        }
126
127
        $data = $this->prepareVerificationData();
128
129
        if (isset($_SERVER['SERVER_PROTOCOL']) && $_SERVER['SERVER_PROTOCOL'] == "HTTP/2.0") {
130
            $context = stream_context_create(
131
                [
132
                'ssl' => array(
133
                  'verify_peer'       => false,
134
                  'verify_peer_name'  => false
135
                )]
136
            );
137
138
            $soap = new \SoapClient($this->settings->apiPurchaseUrl, [
139
                'stream_context' => $context
140
            ]);
141
        } else {
142
            $soap = new \SoapClient($this->settings->apiPurchaseUrl);
143
        }
144
145
        // step1: verify request
146
        $verifyResponse = (int)$soap->bpVerifyRequest($data)->return;
147
        if ($verifyResponse != 0) {
148
            // rollback money and throw exception
149
            // avoid rollback if request was already verified
150
            if ($verifyResponse != 43) {
151
                $soap->bpReversalRequest($data);
152
            }
153
            throw new InvalidPaymentException($this->translateStatus($verifyResponse), $verifyResponse);
154
        }
155
156
        // step2: settle request
157
        $settleResponse = $soap->bpSettleRequest($data)->return;
158
        if ($settleResponse != 0) {
159
            // rollback money and throw exception
160
            // avoid rollback if request was already settled/reversed
161
            if ($settleResponse != 45 && $settleResponse != 48) {
162
                $soap->bpReversalRequest($data);
163
            }
164
            throw new InvalidPaymentException($this->translateStatus($settleResponse), $settleResponse);
165
        }
166
167
        $receipt = $this->createReceipt($data['saleReferenceId']);
168
169
        $receipt->detail([
170
            "RefId" => Request::input('RefId'),
171
            "SaleOrderId" => Request::input('SaleOrderId'),
172
            "CardHolderPan" => Request::input('CardHolderPan'),
173
            "CardHolderInfo" => Request::input('CardHolderInfo'),
174
            "SaleReferenceId" => Request::input('SaleReferenceId'),
175
        ]);
176
177
        return $receipt;
178
    }
179
180
    /**
181
     * @return Receipt
182
     * @throws InvalidPaymentException
183
     * @throws \SoapFault
184
     */
185
    public function refund(): Receipt
186
    {
187
        if (isset($_SERVER['SERVER_PROTOCOL']) && $_SERVER['SERVER_PROTOCOL'] == "HTTP/2.0") {
188
            $context = stream_context_create(
189
                [
190
                    'ssl' => [
191
                        'verify_peer'       => false,
192
                        'verify_peer_name'  => false
193
                    ]
194
                ]
195
            );
196
197
            $soap = new \SoapClient($this->settings->apiRefundUrl, ['stream_context' => $context]);
198
        } else {
199
            $soap = new \SoapClient($this->settings->apiRefundUrl);
200
        }
201
202
        $data = [
203
            'terminalId' => $this->settings->terminalId,
204
            'userName' => $this->settings->username,
205
            'userPassword' => $this->settings->password,
206
            'orderId' => $this->invoice->getUuid(),
207
            'saleOrderId' => $this->invoice->detail('saleOrderId'),
208
            'saleReferenceId' => $this->invoice->detail('saleReferenceId'),
209
            'refundAmount' => $this->invoice->getAmount(),
210
        ];
211
212
        $refundResponse = $soap->bpRefundRequest($data)->return;
213
214
        if ($refundResponse != 0) {
215
            throw new InvalidPaymentException($this->translateStatus($refundResponse), $refundResponse);
216
        }
217
218
        return $this->createReceipt($this->invoice->detail('saleReferenceId'));
219
    }
220
221
    /**
222
     * Generate the payment's receipt
223
     *
224
     * @param $referenceId
225
     *
226
     * @return Receipt
227
     */
228
    protected function createReceipt($referenceId)
229
    {
230
        return new Receipt('behpardakht', $referenceId);
231
    }
232
233
    /**
234
     * Prepare data for payment verification
235
     *
236
     * @return array
237
     */
238
    protected function prepareVerificationData()
239
    {
240
        $orderId = Request::input('SaleOrderId');
241
        $verifySaleOrderId = Request::input('SaleOrderId');
242
        $verifySaleReferenceId = Request::input('SaleReferenceId');
243
244
        return array(
245
            'terminalId' => $this->settings->terminalId,
246
            'userName' => $this->settings->username,
247
            'userPassword' => $this->settings->password,
248
            'orderId' => $orderId,
249
            'saleOrderId' => $verifySaleOrderId,
250
            'saleReferenceId' => $verifySaleReferenceId
251
        );
252
    }
253
254
    /**
255
     * Prepare data for purchasing invoice
256
     *
257
     * @return array
258
     */
259
    protected function preparePurchaseData()
260
    {
261
        if (!empty($this->invoice->getDetails()['description'])) {
262
            $description = $this->invoice->getDetails()['description'];
263
        } else {
264
            $description = $this->settings->description;
265
        }
266
267
        $payerId = $this->invoice->getDetails()['payerId'] ?? 0;
268
269
        return array(
270
            'terminalId' => $this->settings->terminalId,
271
            'userName' => $this->settings->username,
272
            'userPassword' => $this->settings->password,
273
            'callBackUrl' => $this->settings->callbackUrl,
274
            'amount' => $this->invoice->getAmount() * 10, // convert to rial
275
            'localDate' => Carbon::now()->format('Ymd'),
276
            'localTime' => Carbon::now()->format('Gis'),
277
            'orderId' => crc32($this->invoice->getUuid()),
278
            'additionalData' => $description,
279
            'payerId' => $payerId
280
        );
281
    }
282
283
    /**
284
     * Convert status to a readable message.
285
     *
286
     * @param $status
287
     *
288
     * @return mixed|string
289
     */
290
    private function translateStatus($status)
291
    {
292
        $translations = [
293
            '0' => 'تراکنش با موفقیت انجام شد',
294
            '11' => 'شماره کارت نامعتبر است',
295
            '12' => 'موجودی کافی نیست',
296
            '13' => 'رمز نادرست است',
297
            '14' => 'تعداد دفعات وارد کردن رمز بیش از حد مجاز است',
298
            '15' => 'کارت نامعتبر است',
299
            '16' => 'دفعات برداشت وجه بیش از حد مجاز است',
300
            '17' => 'کاربر از انجام تراکنش منصرف شده است',
301
            '18' => 'تاریخ انقضای کارت گذشته است',
302
            '19' => 'مبلغ برداشت وجه بیش از حد مجاز است',
303
            '111' => 'صادر کننده کارت نامعتبر است',
304
            '112' => 'خطای سوییچ صادر کننده کارت',
305
            '113' => 'پاسخی از صادر کننده کارت دریافت نشد',
306
            '114' => 'دارنده کارت مجاز به انجام این تراکنش نیست',
307
            '21' => 'پذیرنده نامعتبر است',
308
            '23' => 'خطای امنیتی رخ داده است',
309
            '24' => 'اطلاعات کاربری پذیرنده نامعتبر است',
310
            '25' => 'مبلغ نامعتبر است',
311
            '31' => 'پاسخ نامعتبر است',
312
            '32' => 'فرمت اطلاعات وارد شده صحیح نمی‌باشد',
313
            '33' => 'حساب نامعتبر است',
314
            '34' => 'خطای سیستمی',
315
            '35' => 'تاریخ نامعتبر است',
316
            '41' => 'شماره درخواست تکراری است',
317
            '42' => 'تراکنش Sale یافت نشد',
318
            '43' => 'قبلا درخواست Verify داده شده است',
319
            '44' => 'درخواست Verify یافت نشد',
320
            '45' => 'تراکنش Settle شده است',
321
            '46' => 'تراکنش Settle نشده است',
322
            '47' => 'تراکنش Settle یافت نشد',
323
            '48' => 'تراکنش Reverse شده است',
324
            '412' => 'شناسه قبض نادرست است',
325
            '413' => 'شناسه پرداخت نادرست است',
326
            '414' => 'سازمان صادر کننده قبض نامعتبر است',
327
            '415' => 'زمان جلسه کاری به پایان رسیده است',
328
            '416' => 'خطا در ثبت اطلاعات',
329
            '417' => 'شناسه پرداخت کننده نامعتبر است',
330
            '418' => 'اشکال در تعریف اطلاعات مشتری',
331
            '419' => 'تعداد دفعات ورود اطلاعات از حد مجاز گذشته است',
332
            '421' => 'IP نامعتبر است',
333
            '51' => 'تراکنش تکراری است',
334
            '54' => 'تراکنش مرجع موجود نیست',
335
            '55' => 'تراکنش نامعتبر است',
336
            '61' => 'خطا در واریز',
337
            '62' => 'مسیر بازگشت به سایت در دامنه ثبت شده برای پذیرنده قرار ندارد',
338
            '98' => 'سقف استفاده از رمز ایستا به پایان رسیده است'
339
        ];
340
341
        $unknownError = 'خطای ناشناخته رخ داده است.';
342
343
        return array_key_exists($status, $translations) ? $translations[$status] : $unknownError;
344
    }
345
}
346