Saman   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 224
Duplicated Lines 0 %

Importance

Changes 5
Bugs 0 Features 1
Metric Value
eloc 96
c 5
b 0
f 1
dl 0
loc 224
rs 10
wmc 13

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A pay() 0 11 1
A notVerified() 0 25 2
A verify() 0 34 2
A purchaseFailed() 0 26 2
A createReceipt() 0 5 1
A purchase() 0 40 4
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\Saman;
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\RedirectionForm;
12
use Shetabit\Multipay\Request;
13
14
class Saman extends Driver
15
{
16
    /**
17
     * Invoice
18
     *
19
     * @var Invoice
20
     */
21
    protected $invoice;
22
23
    /**
24
     * Driver settings
25
     *
26
     * @var object
27
     */
28
    protected $settings;
29
30
    /**
31
     * Saman constructor.
32
     * Construct the class with the relevant settings.
33
     *
34
     * @param Invoice $invoice
35
     * @param $settings
36
     */
37
    public function __construct(Invoice $invoice, $settings)
38
    {
39
        $this->invoice($invoice);
40
        $this->settings = (object)$settings;
41
    }
42
43
    /**
44
     * Purchase Invoice.
45
     *
46
     * @return string
47
     *
48
     * @throws PurchaseFailedException
49
     * @throws \SoapFault
50
     */
51
    public function purchase()
52
    {
53
        $data = array(
54
            'MID' => $this->settings->merchantId,
55
            'ResNum' => $this->invoice->getUuid(),
56
            'Amount' => $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 10 : 1), // convert to rial
57
            'CellNumber' => ''
58
        );
59
60
        //set CellNumber for get user cards
61
        if (!empty($this->invoice->getDetails()['mobile'])) {
62
            $data['CellNumber'] = $this->invoice->getDetails()['mobile'];
63
        }
64
65
        $soap = new \SoapClient(
66
            $this->settings->apiPurchaseUrl,
67
            [
68
                'encoding'       => 'UTF-8',
69
                'cache_wsdl'     => WSDL_CACHE_NONE,
70
                'stream_context' => stream_context_create([
71
                    'ssl' => [
72
                        'ciphers' => 'DEFAULT:!DH',
73
                    ],
74
                ]),
75
            ]
76
        );
77
78
        $response = $soap->RequestToken($data['MID'], $data['ResNum'], $data['Amount'], $data['CellNumber']);
79
80
        $status = (int)$response;
81
82
        if ($status < 0) { // if something has done in a wrong way
83
            $this->purchaseFailed($response);
84
        }
85
86
        // set transaction id
87
        $this->invoice->transactionId($response);
88
89
        // return the transaction's id
90
        return $this->invoice->getTransactionId();
91
    }
92
93
    /**
94
     * Pay the Invoice
95
     *
96
     * @return RedirectionForm
97
     */
98
    public function pay(): RedirectionForm
99
    {
100
        $payUrl = $this->settings->apiPaymentUrl;
101
102
        return $this->redirectWithForm(
103
            $payUrl,
104
            [
105
                'Token' => $this->invoice->getTransactionId(),
106
                'RedirectUrl' => $this->settings->callbackUrl,
107
            ],
108
            'POST'
109
        );
110
    }
111
112
    /**
113
     * Verify payment
114
     *
115
     * @return ReceiptInterface
116
     *
117
     * @throws InvalidPaymentException
118
     * @throws \SoapFault
119
     */
120
    public function verify(): ReceiptInterface
121
    {
122
        $data = array(
123
            'RefNum' => Request::input('RefNum'),
124
            'merchantId' => $this->settings->merchantId,
125
        );
126
127
        $soap = new \SoapClient(
128
            $this->settings->apiVerificationUrl,
129
            [
130
                'encoding'       => 'UTF-8',
131
                'cache_wsdl'     => WSDL_CACHE_NONE,
132
                'stream_context' => stream_context_create([
133
                    'ssl' => [
134
                        'ciphers' => 'DEFAULT:!DH',
135
                    ],
136
                ]),
137
            ]
138
        );
139
        $status = (int)$soap->VerifyTransaction($data['RefNum'], $data['merchantId']);
140
141
        if ($status < 0) {
142
            $this->notVerified($status);
143
        }
144
145
        $receipt =  $this->createReceipt($data['RefNum']);
146
        $receipt->detail([
147
            'traceNo' => Request::input('TraceNo'),
148
            'referenceNo' => Request::input('RRN'),
149
            'transactionId' => Request::input('RefNum'),
150
            'cardNo' => Request::input('SecurePan'),
151
        ]);
152
153
        return $receipt;
154
    }
155
156
    /**
157
     * Generate the payment's receipt
158
     *
159
     * @param $referenceId
160
     *
161
     * @return Receipt
162
     */
163
    protected function createReceipt($referenceId)
164
    {
165
        $receipt = new Receipt('saman', $referenceId);
166
167
        return $receipt;
168
    }
169
170
    /**
171
     * Trigger an exception
172
     *
173
     * @param $status
174
     *
175
     * @throws PurchaseFailedException
176
     */
177
    protected function purchaseFailed($status)
178
    {
179
        $translations = array(
180
            -1 => ' تراکنش توسط خریدار کنسل شده است.',
181
            -6 => 'سند قابل برگشت کامل یافته است. یا خارج از زمان 30 دقیقه ارسال شده است.',
182
            -18 => 'IP Address فروشنده نا‌معتبر است.',
183
            79 => 'مبلغ سند برگشتی، از مبلغ تراکنش اصلی بیشتر است.',
184
            12 => 'درخواست برگشت یک تراکنش رسیده است، در حالی که تراکنش اصلی پیدا نمی شود.',
185
            14 => 'شماره کارت نامعتبر است.',
186
            15 => 'چنین صادر کننده کارتی وجود ندارد.',
187
            33 => 'از تاریخ انقضای کارت گذشته است و کارت دیگر معتبر نیست.',
188
            38 => 'رمز کارت 3 مرتبه اشتباه وارد شده است در نتیجه کارت غیر فعال خواهد شد.',
189
            55 => 'خریدار رمز کارت را اشتباه وارد کرده است.',
190
            61 => 'مبلغ بیش از سقف برداشت می باشد.',
191
            93 => 'تراکنش Authorize شده است (شماره PIN و PAN درست هستند) ولی امکان سند خوردن وجود ندارد.',
192
            68 => 'تراکنش در شبکه بانکی Timeout خورده است.',
193
            34 => 'خریدار یا فیلد CVV2 و یا فیلد ExpDate را اشتباه وارد کرده است (یا اصلا وارد نکرده است).',
194
            51 => 'موجودی حساب خریدار، کافی نیست.',
195
            84 => 'سیستم بانک صادر کننده کارت خریدار، در وضعیت عملیاتی نیست.',
196
            96 => 'کلیه خطاهای دیگر بانکی باعث ایجاد چنین خطایی می گردد.',
197
        );
198
199
        if (array_key_exists($status, $translations)) {
200
            throw new PurchaseFailedException($translations[$status]);
201
        } else {
202
            throw new PurchaseFailedException('خطای ناشناخته ای رخ داده است.');
203
        }
204
    }
205
206
    /**
207
     * Trigger an exception
208
     *
209
     * @param $status
210
     *
211
     * @throws InvalidPaymentException
212
     */
213
    private function notVerified($status)
214
    {
215
        $translations = array(
216
            -1 => 'خطا در پردازش اطلاعات ارسالی (مشکل در یکی از ورودی ها و ناموفق بودن فراخوانی متد برگشت تراکنش)',
217
            -3 => 'ورودی ها حاوی کارکترهای غیرمجاز میباشند.',
218
            -4 => 'کلمه عبور یا کد فروشنده اشتباه است (Merchant Authentication Failed)',
219
            -6 => 'سند قابل برگشت کامل یافته است. یا خارج از زمان 30 دقیقه ارسال شده است.',
220
            -7 => 'رسید دیجیتالی تهی است.',
221
            -8 => 'طول ورودی ها بیشتر از حد مجاز است.',
222
            -9 => 'وجود کارکترهای غیرمجاز در مبلغ برگشتی.',
223
            -10 => 'رسید دیجیتالی به صورت Base64 نیست (حاوی کاراکترهای غیرمجاز است)',
224
            -11 => 'طول ورودی ها کمتر از حد مجاز است.',
225
            -12 => 'مبلغ برگشتی منفی است.',
226
            -13 => 'مبلغ برگشتی برای برگشت جزئی بیش از مبلغ برگشت نخورده ی رسید دیجیتالی است.',
227
            -14 => 'چنین تراکنشی تعریف نشده است.',
228
            -15 => 'مبلغ برگشتی به صورت اعشاری داده شده است.',
229
            -16 => 'خطای داخلی سیستم',
230
            -17 => 'برگشت زدن جزیی تراکنش مجاز نمی باشد.',
231
            -18 => 'IP Address فروشنده نا معتبر است و یا رمز تابع بازگشتی (reverseTransaction) اشتباه است.',
232
        );
233
234
        if (array_key_exists($status, $translations)) {
235
            throw new InvalidPaymentException($translations[$status], (int)$status);
236
        } else {
237
            throw new InvalidPaymentException('خطای ناشناخته ای رخ داده است.', (int)$status);
238
        }
239
    }
240
}
241