Passed
Push — master ( efe50c...6a7137 )
by mahdi
02:57
created

SEP::verify()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 41
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 23
c 1
b 0
f 0
nc 8
nop 0
dl 0
loc 41
rs 9.552
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\SEP;
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 SEP extends Driver
16
{
17
    /**
18
     * SEP HTTP Client.
19
     *
20
     * @var object
21
     */
22
    protected $client;
23
24
    /**
25
     * Invoice
26
     *
27
     * @var Invoice
28
     */
29
    protected $invoice;
30
31
    /**
32
     * Driver settings
33
     *
34
     * @var object
35
     */
36
    protected $settings;
37
38
    /**
39
     * SEP constructor.
40
     * Construct the class with the relevant settings.
41
     *
42
     * @param Invoice $invoice
43
     * @param $settings
44
     */
45
    public function __construct(Invoice $invoice, $settings)
46
    {
47
        $this->invoice($invoice);
48
        $this->settings = (object)$settings;
49
        $this->client = new Client([
50
            'curl' => [CURLOPT_SSL_CIPHER_LIST => 'DEFAULT@SECLEVEL=1'],
51
        ]);
52
    }
53
54
    /**
55
     * Purchase Invoice.
56
     *
57
     * @return string
58
     *
59
     * @throws PurchaseFailedException
60
     * @throws \SoapFault
61
     */
62
    public function purchase()
63
    {
64
        $data = array(
65
            'action' => 'token',
66
            'TerminalId' => $this->settings->terminalId,
67
            'Amount' => $this->invoice->getAmount() * 10, // convert to rial
68
            'ResNum' => $this->invoice->getUuid(),
69
            'RedirectUrl' => $this->settings->callbackUrl,
70
            'CellNumber' => $this->invoice->getDetail('mobile') ?? '',
71
            'ResNum1' => $this->invoice->getDetail('ResNum1') ?? '',
72
            'ResNum2' => $this->invoice->getDetail('ResNum2') ?? '',
73
            'ResNum3' => $this->invoice->getDetail('ResNum3') ?? '',
74
            'ResNum4' => $this->invoice->getDetail('ResNum4') ?? '',
75
        );
76
77
        $response = $this->client->post(
78
            $this->settings->apiGetToken,
79
            [
80
                'json' => $data,
81
            ]
82
        );
83
84
        $responseStatus = $response->getStatusCode();
85
86
        if ($responseStatus != 200) { // if something has done in a wrong way
87
            $this->purchaseFailed(0);
88
        }
89
90
        $jsonBody = $response->getBody()->getContents();
91
        $responseData = json_decode($jsonBody, true);
92
93
        if ($responseData['status'] != 1) {
94
            $this->purchaseFailed($responseData['errorCode']);
95
        }
96
97
        // set transaction id
98
        $this->invoice->transactionId($responseData['token']);
99
100
        // return the transaction's id
101
        return $this->invoice->getTransactionId();
102
    }
103
104
    /**
105
     * Pay the Invoice
106
     *
107
     * @return RedirectionForm
108
     */
109
    public function pay(): RedirectionForm
110
    {
111
        $payUrl = $this->settings->apiPaymentUrl;
112
113
        return $this->redirectWithForm(
114
            $payUrl,
115
            [
116
                'Token' => $this->invoice->getTransactionId(),
117
                'GetMethod' => false,
118
            ]
119
        );
120
    }
121
122
    /**
123
     * Verify payment
124
     *
125
     * @return ReceiptInterface
126
     *
127
     * @throws InvalidPaymentException
128
     * @throws \SoapFault
129
     * @throws PurchaseFailedException
130
     */
131
    public function verify(): ReceiptInterface
132
    {
133
        $status = (int)Request::input('Status');
134
        if ($status != 2) {
135
            $this->purchaseFailed($status);
136
        }
137
138
        $data = array(
139
            'RefNum' => Request::input('RefNum'),
140
            'TerminalNumber' => $this->settings->terminalId,
141
        );
142
143
        $response = $this->client->post(
144
            $this->settings->apiVerificationUrl,
145
            [
146
                'json' => $data,
147
            ]
148
        );
149
150
        if ($response->getStatusCode() != 200) {
151
            $this->notVerified(0);
152
        }
153
154
        $jsonData = $response->getBody()->getContents();
155
        $responseData = json_decode($jsonData, true);
156
157
        if ($responseData['ResultCode'] != 0) {
158
            $this->notVerified($responseData['ResultCode']);
159
        }
160
161
        $transactionDetail = $responseData['TransactionDetail'];
162
163
        $receipt = $this->createReceipt($data['RefNum']);
164
        $receipt->detail([
165
            'traceNo' => $transactionDetail['StraceNo'],
166
            'referenceNo' => $transactionDetail['RRN'],
167
            'transactionId' => $transactionDetail['RefNum'],
168
            'cardNo' => $transactionDetail['MaskedPan'],
169
        ]);
170
171
        return $receipt;
172
    }
173
174
    /**
175
     * Generate the payment's receipt
176
     *
177
     * @param $referenceId
178
     *
179
     * @return Receipt
180
     */
181
    protected function createReceipt($referenceId)
182
    {
183
        $receipt = new Receipt('saman', $referenceId);
184
185
        return $receipt;
186
    }
187
188
    /**
189
     * Trigger an exception
190
     *
191
     * @param $status
192
     *
193
     * @throws PurchaseFailedException
194
     */
195
    protected function purchaseFailed($status)
196
    {
197
        $translations = array(
198
            1 => ' تراکنش توسط خریدار کنسل شده است.',
199
            2 => 'پرداخت با موفقیت انجام شد.',
200
            3 => 'پرداخت انجام نشد.',
201
            4 => 'کاربر در بازه زمانی تعیین شده پاسخی ارسال نکرده است.',
202
            5 => 'پارامترهای ارسالی نامعتبر است.',
203
            8 => 'آدرس سرور پذیرنده نامعتبر است.',
204
            9 => 'رمز کارت 3 مرتبه اشتباه وارد شده است در نتیجه کارت غیر فعال خواهد شد.',
205
            10 => 'توکن ارسال شده یافت نشد.',
206
            11 => 'با این شماره ترمینال فقط تراکنش های توکنی قابل پرداخت هستند.',
207
            12 => 'شماره ترمینال ارسال شده یافت نشد.',
208
        );
209
210
        if (array_key_exists($status, $translations)) {
211
            throw new PurchaseFailedException($translations[$status]);
212
        } else {
213
            throw new PurchaseFailedException('خطای ناشناخته ای رخ داده است.');
214
        }
215
    }
216
217
    /**
218
     * Trigger an exception
219
     *
220
     * @param $status
221
     *
222
     * @throws InvalidPaymentException
223
     */
224
    private function notVerified($status)
225
    {
226
        $translations = array(
227
            -2 => ' تراکنش یافت نشد.',
228
            -6 => 'بیش از نیم ساعت از زمان اجرای تراکنش گذشته است.',
229
            2 => 'کاربر در بازه زمانی تعیین شده پاسخی ارسال نکرده است.',
230
            -104 => 'پارامترهای ارسالی نامعتبر است.',
231
            -105 => 'آدرس سرور پذیرنده نامعتبر است.',
232
            -106 => 'رمز کارت 3 مرتبه اشتباه وارد شده است در نتیجه کارت غیر فعال خواهد شد.',
233
        );
234
235
        if (array_key_exists($status, $translations)) {
236
            throw new InvalidPaymentException($translations[$status]);
237
        } else {
238
            throw new InvalidPaymentException('خطای ناشناخته ای رخ داده است.');
239
        }
240
    }
241
}
242