SEP   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 235
Duplicated Lines 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
eloc 93
c 3
b 1
f 0
dl 0
loc 235
rs 10
wmc 15

7 Methods

Rating   Name   Duplication   Size   Complexity  
A pay() 0 9 1
A __construct() 0 6 1
A purchase() 0 40 4
A notVerified() 0 15 2
A purchaseFailed() 0 19 2
A createReceipt() 0 5 1
A verify() 0 52 4
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() * ($this->settings->currency == 'T' ? 10 : 1), // 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
        // Add additional data specific for SEP gateway
172
        $receipt->detail([
173
            'TerminalNumber' => $transactionDetail['TerminalNumber'],
174
            'OrginalAmount' => $transactionDetail['OrginalAmount'],
175
            'AffectiveAmount' => $transactionDetail['AffectiveAmount'],
176
            'StraceDate' => $transactionDetail['StraceDate'],
177
            // SEP documents are not up-to-date. This will fix different
178
            // between variable name in docs and actual returned values.
179
            'Amount' => $transactionDetail['OrginalAmount'],
180
        ]);
181
        
182
        return $receipt;
183
    }
184
185
    /**
186
     * Generate the payment's receipt
187
     *
188
     * @param $referenceId
189
     *
190
     * @return Receipt
191
     */
192
    protected function createReceipt($referenceId)
193
    {
194
        $receipt = new Receipt('saman', $referenceId);
195
196
        return $receipt;
197
    }
198
199
    /**
200
     * Trigger an exception
201
     *
202
     * @param $status
203
     *
204
     * @throws PurchaseFailedException
205
     */
206
    protected function purchaseFailed($status)
207
    {
208
        $translations = array(
209
            1 => ' تراکنش توسط خریدار لغو شده است.',
210
            2 => 'پرداخت با موفقیت انجام شد.',
211
            3 => 'پرداخت انجام نشد.',
212
            4 => 'کاربر در بازه زمانی تعیین شده پاسخی ارسال نکرده است.',
213
            5 => 'پارامترهای ارسالی نامعتبر است.',
214
            8 => 'آدرس سرور پذیرنده نامعتبر است.',
215
            9 => 'رمز کارت 3 مرتبه اشتباه وارد شده است در نتیجه کارت غیر فعال خواهد شد.',
216
            10 => 'توکن ارسال شده یافت نشد.',
217
            11 => 'با این شماره ترمینال فقط تراکنش های توکنی قابل پرداخت هستند.',
218
            12 => 'شماره ترمینال ارسال شده یافت نشد.',
219
        );
220
221
        if (array_key_exists($status, $translations)) {
222
            throw new PurchaseFailedException($translations[$status]);
223
        } else {
224
            throw new PurchaseFailedException('خطای ناشناخته ای رخ داده است.');
225
        }
226
    }
227
228
    /**
229
     * Trigger an exception
230
     *
231
     * @param $status
232
     *
233
     * @throws InvalidPaymentException
234
     */
235
    private function notVerified($status)
236
    {
237
        $translations = array(
238
            -2 => ' تراکنش یافت نشد.',
239
            -6 => 'بیش از 30 دقیقه از زمان اجرای تراکنش گذشته است.',
240
            2 => 'کاربر در بازه زمانی تعیین شده پاسخی ارسال نکرده است.',
241
            -104 => 'پارامترهای ارسالی نامعتبر است.',
242
            -105 => 'آدرس سرور پذیرنده نامعتبر است.',
243
            -106 => 'رمز کارت 3 مرتبه اشتباه وارد شده است در نتیجه کارت غیر فعال خواهد شد.',
244
        );
245
246
        if (array_key_exists($status, $translations)) {
247
            throw new InvalidPaymentException($translations[$status], (int)$status);
248
        } else {
249
            throw new InvalidPaymentException('خطای ناشناخته ای رخ داده است.', (int)$status);
250
        }
251
    }
252
}
253