Passed
Push — master ( 862f3b...6941da )
by mahdi
03:41
created

Asanpardakht::verifyStep()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 7
c 1
b 0
f 0
dl 0
loc 11
rs 10
cc 3
nc 3
nop 2
1
<?php
2
3
namespace Shetabit\Payment\Drivers\Asanpardakht;
4
5
use Shetabit\Payment\Abstracts\Driver;
6
use Shetabit\Payment\Exceptions\InvalidPaymentException;
7
use Shetabit\Payment\Exceptions\PurchaseFailedException;
8
use Shetabit\Payment\Contracts\ReceiptInterface;
9
use Shetabit\Payment\Invoice;
10
use Shetabit\Payment\Receipt;
11
12
class Asanpardakht extends Driver
13
{
14
    /**
15
     * Invoice
16
     *
17
     * @var Invoice
18
     */
19
    protected $invoice;
20
21
    /**
22
     * Driver settings
23
     *
24
     * @var object
25
     */
26
    protected $settings;
27
28
    /**
29
     * Asanpardakht constructor.
30
     * Construct the class with the relevant settings.
31
     *
32
     * @param Invoice $invoice
33
     * @param $settings
34
     */
35
    public function __construct(Invoice $invoice, $settings)
36
    {
37
        $this->invoice($invoice);
38
        $this->settings = (object)$settings;
39
    }
40
41
    /**
42
     * Purchase Invoice.
43
     *
44
     * @return string
45
     *
46
     * @throws PurchaseFailedException
47
     * @throws \SoapFault
48
     */
49
    public function purchase()
50
    {
51
        $client = $this->createSoapClient($this->settings->apiPurchaseUrl);
52
53
        $params = $this->preparePurchaseData();
54
        $result = $client->RequestOperation($params);
55
        if (! $result) {
56
            throw  new PurchaseFailedException('خطای فراخوانی متد درخواست تراکنش.');
57
        }
58
59
        $result = $result->RequestOperationResult;
60
        if ($result{0} != '0') {
61
            $message = "خطای شماره ".$result." رخ داده است.";
62
            throw  new PurchaseFailedException($message);
63
        }
64
65
        $this->invoice->transactionId(substr($result, 2));
66
67
        // return the transaction's id
68
        return $this->invoice->getTransactionId();
69
    }
70
71
    /**
72
     * Pay the Invoice
73
     *
74
     * @return \Illuminate\Http\RedirectResponse|mixed
75
     */
76
    public function pay()
77
    {
78
        $payUrl = $this->settings->apiPaymentUrl;
79
80
        return $this->redirectWithForm(
81
            $payUrl,
82
            ['RefId' => $this->invoice->getTransactionId()],
83
            'POST'
84
        );
85
    }
86
87
    /**
88
     * Verify payment
89
     *
90
     * @return mixed|Receipt
91
     *
92
     * @throws InvalidPaymentException
93
     * @throws \SoapFault
94
     */
95
    public function verify() : ReceiptInterface
96
    {
97
        $encryptedReturningParamsString = request()->get('ReturningParams');
98
        $returningParamsString = decrypt($encryptedReturningParamsString);
99
        $returningParams = explode(",", $returningParamsString);
100
101
        /**
102
         * other data:
103
         *   $amount = $returningParams[0];
104
         *   $saleOrderId = $returningParams[1];
105
         *   $refId = $this->invoice->getTransactionId() ?? $returningParams[2];
106
         *   $resMessage = $returningParams[4];
107
         *   $rrn = $returningParams[6];
108
         *   $lastFourDigitOfPAN = $returningParams[7];
109
        **/
110
111
        $resCode = $returningParams[3];
112
        $payGateTranID = $returningParams[5];
113
114
        if ($resCode != '0' && $resCode != '00') {
115
            $message =  "خطای شماره " . $resCode . " رخ داده و تراکنش ناموفق بوده است.";
116
            throw new InvalidPaymentException($message);
117
        }
118
119
        $client = $this->createSoapClient($this->settings->apiVerificationUrl);
120
        $params = $this->prepareVerificationData($payGateTranID);
121
122
        // step1: verify
123
        $this->verifyStep($client, $params);
124
125
        // step2: settle
126
        $this->settleStep($client, $params);
127
128
        return $this->createReceipt($payGateTranID);
129
    }
130
131
    /**
132
     * payment verification step
133
     *
134
     * @param $client
135
     * @param $params
136
     *
137
     * @throws InvalidPaymentException
138
     */
139
    protected function verifyStep($client, $params)
140
    {
141
        $result = $client->RequestVerification($params);
142
        if (! $result) {
143
            throw new InvalidPaymentException("خطای فراخوانی متد وريفای رخ داده است.");
144
        }
145
146
        $result = $result->RequestVerificationResult;
147
        if ($result != '500') {
148
            $message = "خطای شماره: ".$result." در هنگام Verify";
149
            throw  new InvalidPaymentException($message);
150
        }
151
    }
152
153
    /**
154
     * payment settlement step.
155
     *
156
     * @param $client
157
     * @param $params
158
     *
159
     * @throws InvalidPaymentException
160
     */
161
    protected function settleStep($client, $params) {
162
        $result = $client->RequestReconciliation($params);
163
        if (! $result) {
164
            throw new InvalidPaymentException('خطای فراخوانی متد تسويه رخ داده است.');
165
        }
166
167
        $result = $result->RequestReconciliationResult;
168
        if ($result != '600') {
169
            $message = "خطای شماره: ".$result." در هنگام Settlement";
170
            throw new InvalidPaymentException($message);
171
        }
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('asanpardakht', $referenceId);
184
185
        return $receipt;
186
    }
187
188
    /**
189
     * Prepare data for payment verification
190
     *
191
     * @param $payGateTranID
192
     *
193
     * @return array
194
     *
195
     * @throws \SoapFault
196
     */
197
    protected function prepareVerificationData($payGateTranID)
198
    {
199
        $credentials = array(
200
            $this->settings->username,
201
            $this->settings->password
202
        );
203
204
        $encryptedCredentials = $this->encrypt(implode(',', $credentials));
205
206
        return array(
207
            'merchantConfigurationID' => $this->settings->merchantId,
208
            'encryptedCredentials' => $encryptedCredentials,
209
            'payGateTranID' => $payGateTranID
210
        );
211
    }
212
213
    /**
214
     * Prepare data for purchasing invoice
215
     *
216
     * @return array
217
     *
218
     * @throws \SoapFault
219
     */
220
    protected function preparePurchaseData()
221
    {
222
        if (!empty($this->invoice->getDetails()['description'])) {
223
            $description = $this->invoice->getDetails()['description'];
224
        } else {
225
            $description = $this->settings->description;
226
        }
227
228
        // configs
229
        $username = $this->settings->username;
230
        $password = $this->settings->password;
231
        $callBackUrl = $this->settings->callbackUrl;
232
233
        // invoice details
234
        $price = $this->invoice->getAmount() * 10; // convert to rial
235
        $additionalData = $description ?? '';
236
        $orderId = crc32($this->invoice->getUuid());
237
        $localDate = date("Ymd His");
238
239
        // box and encrypt everything
240
        $requestString = "1,{$username},{$password},{$orderId},{$price},{$localDate},{$additionalData},{$callBackUrl},0";
241
        $encryptedRequestString = $this->encrypt($requestString);
242
243
        return array(
244
            'merchantConfigurationID' => $this->settings->merchantId,
245
            'encryptedRequest' => $encryptedRequestString
246
        );
247
    }
248
249
    /**
250
     * Encrypt given string.
251
     *
252
     * @param $string
253
     *
254
     * @return mixed
255
     *
256
     * @throws \SoapFault
257
     */
258
    protected function encrypt($string)
259
    {
260
        $client = $this->createSoapClient($this->settings->apiUtilsUrl);
261
262
        $params = array(
263
            'aesKey' => $this->settings->key,
264
            'aesVector' => $this->settings->iv,
265
            'toBeEncrypted' => $string
266
        );
267
268
        $result = $client->EncryptInAES($params);
269
270
        return $result->EncryptInAESResult;
271
    }
272
273
    /**
274
     * Decrypt given string.
275
     *
276
     * @param $string
277
     *
278
     * @return mixed
279
     *
280
     * @throws \SoapFault
281
     */
282
    protected function decrypt($string)
283
    {
284
        $client = $this->createSoapClient($this->settings->apiUtilsUrl);
285
286
        $params = array(
287
            'aesKey' => $this->settings->key,
288
            'aesVector' => $this->settings->iv,
289
            'toBeDecrypted' => $string
290
        );
291
292
        $result = $client->DecryptInAES($params);
293
294
        return $result->DecryptInAESResult;
295
    }
296
297
    /**
298
     * create a new SoapClient
299
     *
300
     * @param $url
301
     *
302
     * @return \SoapClient
303
     *
304
     * @throws \SoapFault
305
     */
306
    protected function createSoapClient($url)
307
    {
308
        $opts = array(
309
            'ssl' => array(
310
                'verify_peer'=>false,
311
                'verify_peer_name'=>false
312
            )
313
        );
314
315
        $configs = array('stream_context' => stream_context_create($opts));
316
317
        return new \SoapClient($url, $configs);
318
    }
319
}
320