Passed
Push — master ( 362d3b...6bb439 )
by mahdi
02:52
created

Behpardakht::verify()   B

Complexity

Conditions 7
Paths 6

Size

Total Lines 33
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 1 Features 0
Metric Value
cc 7
eloc 16
c 4
b 1
f 0
nc 6
nop 0
dl 0
loc 33
rs 8.8333
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
        $soap = new \SoapClient($this->settings->apiPurchaseUrl);
56
        $response = $soap->bpPayRequest($this->preparePurchaseData());
57
58
        // fault has happened in bank gateway
59
        if ($response->return == 21) {
60
            throw new PurchaseFailedException('پذیرنده معتبر نیست.', 21);
61
        }
62
63
        $data = explode(',', $response->return);
64
65
        // purchase was not successful
66
        if ($data[0] != "0") {
67
            throw new PurchaseFailedException($this->translateStatus($data[0]), (int) $data[0]);
68
        }
69
70
        $this->invoice->transactionId($data[1]);
71
72
        // return the transaction's id
73
        return $this->invoice->getTransactionId();
74
    }
75
76
    /**
77
     * Pay the Invoice
78
     *
79
     * @return RedirectionForm
80
     */
81
    public function pay() : RedirectionForm
82
    {
83
        $payUrl = $this->settings->apiPaymentUrl;
84
85
        return $this->redirectWithForm(
86
            $payUrl,
87
            [
88
                'RefId' => $this->invoice->getTransactionId(),
89
            ],
90
            'POST'
91
        );
92
    }
93
94
    /**
95
     * Verify payment
96
     *
97
     * @return mixed|Receipt
98
     *
99
     * @throws InvalidPaymentException
100
     * @throws \SoapFault
101
     */
102
    public function verify() : ReceiptInterface
103
    {
104
        $resCode = Request::input('ResCode');
105
        if ($resCode != '0') {
106
            throw new InvalidPaymentException($this->translateStatus($resCode), $resCode);
107
        }
108
109
        $data = $this->prepareVerificationData();
110
        $soap = new \SoapClient($this->settings->apiVerificationUrl);
111
112
        // step1: verify request
113
        $verifyResponse = (int)$soap->bpVerifyRequest($data)->return;
114
        if ($verifyResponse != 0) {
115
            // rollback money and throw exception
116
            // avoid rollback if request was already verified
117
            if ($verifyResponse != 43) {
118
                $soap->bpReversalRequest($data);
119
            }
120
            throw new InvalidPaymentException($this->translateStatus($verifyResponse), $verifyResponse);
121
        }
122
123
        // step2: settle request
124
        $settleResponse = $soap->bpSettleRequest($data)->return;
125
        if ($settleResponse != 0) {
126
            // rollback money and throw exception
127
            // avoid rollback if request was already settled/reversed
128
            if ($settleResponse != 45 && $settleResponse != 48) {
129
                $soap->bpReversalRequest($data);
130
            }
131
            throw new InvalidPaymentException($this->translateStatus($settleResponse), $settleResponse);
132
        }
133
134
        return $this->createReceipt($data['saleReferenceId']);
135
    }
136
137
    /**
138
     * Generate the payment's receipt
139
     *
140
     * @param $referenceId
141
     *
142
     * @return Receipt
143
     */
144
    protected function createReceipt($referenceId)
145
    {
146
        return new Receipt('behpardakht', $referenceId);
147
    }
148
149
    /**
150
     * Prepare data for payment verification
151
     *
152
     * @return array
153
     */
154
    protected function prepareVerificationData()
155
    {
156
        $orderId = Request::input('SaleOrderId');
157
        $verifySaleOrderId = Request::input('SaleOrderId');
158
        $verifySaleReferenceId = Request::input('SaleReferenceId');
159
160
        return array(
161
            'terminalId'        => $this->settings->terminalId,
162
            'userName'          => $this->settings->username,
163
            'userPassword'      => $this->settings->password,
164
            'orderId'           => $orderId,
165
            'saleOrderId'       => $verifySaleOrderId,
166
            'saleReferenceId'   => $verifySaleReferenceId
167
        );
168
    }
169
170
    /**
171
     * Prepare data for purchasing invoice
172
     *
173
     * @return array
174
     */
175
    protected function preparePurchaseData()
176
    {
177
        if (!empty($this->invoice->getDetails()['description'])) {
178
            $description = $this->invoice->getDetails()['description'];
179
        } else {
180
            $description = $this->settings->description;
181
        }
182
183
        $payerId = $this->invoice->getDetails()['payerId'] ?? 0;
184
185
        return array(
186
            'terminalId'        => $this->settings->terminalId,
187
            'userName'          => $this->settings->username,
188
            'userPassword'      => $this->settings->password,
189
            'callBackUrl'       => $this->settings->callbackUrl,
190
            'amount'            => $this->invoice->getAmount() * 10, // convert to rial
191
            'localDate'         => Carbon::now()->format('Ymd'),
192
            'localTime'         => Carbon::now()->format('Gis'),
193
            'orderId'           => crc32($this->invoice->getUuid()),
194
            'additionalData'    => $description,
195
            'payerId'           => $payerId
196
        );
197
    }
198
199
    /**
200
     * Convert status to a readable message.
201
     *
202
     * @param $status
203
     *
204
     * @return mixed|string
205
     */
206
    private function translateStatus($status)
207
    {
208
        $translations = [
209
            '0' => 'تراکنش با موفقیت انجام شد',
210
            '11' => 'شماره کارت نامعتبر است',
211
            '12' => 'موجودی کافی نیست',
212
            '13' => 'رمز نادرست است',
213
            '14' => 'تعداد دفعات وارد کردن رمز بیش از حد مجاز است',
214
            '15' => 'کارت نامعتبر است',
215
            '16' => 'دفعات برداشت وجه بیش از حد مجاز است',
216
            '17' => 'کاربر از انجام تراکنش منصرف شده است',
217
            '18' => 'تاریخ انقضای کارت گذشته است',
218
            '19' => 'مبلغ برداشت وجه بیش از حد مجاز است',
219
            '111' => 'صادر کننده کارت نامعتبر است',
220
            '112' => 'خطای سوییچ صادر کننده کارت',
221
            '113' => 'پاسخی از صادر کننده کارت دریافت نشد',
222
            '114' => 'دارنده کارت مجاز به انجام این تراکنش نیست',
223
            '21' => 'پذیرنده نامعتبر است',
224
            '23' => 'خطای امنیتی رخ داده است',
225
            '24' => 'اطلاعات کاربری پذیرنده نامعتبر است',
226
            '25' => 'مبلغ نامعتبر است',
227
            '31' => 'پاسخ نامعتبر است',
228
            '32' => 'فرمت اطلاعات وارد شده صحیح نمی‌باشد',
229
            '33' => 'حساب نامعتبر است',
230
            '34' => 'خطای سیستمی',
231
            '35' => 'تاریخ نامعتبر است',
232
            '41' => 'شماره درخواست تکراری است',
233
            '42' => 'تراکنش Sale یافت نشد',
234
            '43' => 'قبلا درخواست Verify داده شده است',
235
            '44' => 'درخواست Verify یافت نشد',
236
            '45' => 'تراکنش Settle شده است',
237
            '46' => 'تراکنش Settle نشده است',
238
            '47' => 'تراکنش Settle یافت نشد',
239
            '48' => 'تراکنش Reverse شده است',
240
            '412' => 'شناسه قبض نادرست است',
241
            '413' => 'شناسه پرداخت نادرست است',
242
            '414' => 'سازمان صادر کننده قبض نامعتبر است',
243
            '415' => 'زمان جلسه کاری به پایان رسیده است',
244
            '416' => 'خطا در ثبت اطلاعات',
245
            '417' => 'شناسه پرداخت کننده نامعتبر است',
246
            '418' => 'اشکال در تعریف اطلاعات مشتری',
247
            '419' => 'تعداد دفعات ورود اطلاعات از حد مجاز گذشته است',
248
            '421' => 'IP نامعتبر است',
249
            '51' => 'تراکنش تکراری است',
250
            '54' => 'تراکنش مرجع موجود نیست',
251
            '55' => 'تراکنش نامعتبر است',
252
            '61' => 'خطا در واریز',
253
            '62' => 'مسیر بازگشت به سایت در دامنه ثبت شده برای پذیرنده قرار ندارد',
254
            '98' => 'سقف استفاده از رمز ایستا به پایان رسیده است'
255
        ];
256
257
        $unknownError = 'خطای ناشناخته رخ داده است.';
258
259
        return array_key_exists($status, $translations) ? $translations[$status] : $unknownError;
260
    }
261
}
262