Passed
Push — master ( b16d7f...fcc73a )
by mahdi
03:36
created

Asanpardakht::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 2
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
nc 1
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
        $result = $client->RequestVerification($params);
124
        if (! $result) {
125
            throw new InvalidPaymentException("خطای فراخوانی متد وريفای رخ داده است.");
126
        }
127
128
        $result = $result->RequestVerificationResult;
129
        if ($result != '500') {
130
            $message = "خطای شماره: ".$result." در هنگام Verify";
131
            throw  new InvalidPaymentException($message);
132
        }
133
134
        // step2: settle
135
        $result = $client->RequestReconciliation($params);
136
        if (! $result) {
137
            throw new InvalidPaymentException('خطای فراخوانی متد تسويه رخ داده است.');
138
        }
139
140
        $result = $result->RequestReconciliationResult;
141
        if ($result != '600') {
142
            $message = "خطای شماره: ".$result." در هنگام Settlement";
143
            throw new InvalidPaymentException($message);
144
        }
145
146
        return $this->createReceipt($payGateTranID);
147
    }
148
149
    /**
150
     * Generate the payment's receipt
151
     *
152
     * @param $referenceId
153
     *
154
     * @return Receipt
155
     */
156
    public function createReceipt($referenceId)
157
    {
158
        $receipt = new Receipt('asanpardakht', $referenceId);
159
160
        return $receipt;
161
    }
162
163
    /**
164
     * Prepare data for payment verification
165
     *
166
     * @param $payGateTranID
167
     *
168
     * @return array
169
     *
170
     * @throws \SoapFault
171
     */
172
    public function prepareVerificationData($payGateTranID)
173
    {
174
        $credentials = array(
175
            $this->settings->username,
176
            $this->settings->password
177
        );
178
179
        $encryptedCredentials = $this->encrypt(implode(',', $credentials));
180
181
        return array(
182
            'merchantConfigurationID' => $this->settings->merchantId,
183
            'encryptedCredentials' => $encryptedCredentials,
184
            'payGateTranID' => $payGateTranID
185
        );
186
    }
187
188
    /**
189
     * Prepare data for purchasing invoice
190
     *
191
     * @return array
192
     *
193
     * @throws \SoapFault
194
     */
195
    protected function preparePurchaseData()
196
    {
197
        if (!empty($this->invoice->getDetails()['description'])) {
198
            $description = $this->invoice->getDetails()['description'];
199
        } else {
200
            $description = $this->settings->description;
201
        }
202
203
        // configs
204
        $username = $this->settings->username;
205
        $password = $this->settings->password;
206
        $callBackUrl = $this->settings->callbackUrl;
207
208
        // invoice details
209
        $price = $this->invoice->getAmount() * 10; // convert to rial
210
        $additionalData = $description ?? '';
211
        $orderId = crc32($this->invoice->getUuid());
212
        $localDate = date("Ymd His");
213
214
        // box and encrypt everything
215
        $requestString = "1,{$username},{$password},{$orderId},{$price},{$localDate},{$additionalData},{$callBackUrl},0";
216
        $encryptedRequestString = $this->encrypt($requestString);
217
218
        return array(
219
            'merchantConfigurationID' => $this->settings->merchantId,
220
            'encryptedRequest' => $encryptedRequestString
221
        );
222
    }
223
224
    /**
225
     * Encrypt given string.
226
     *
227
     * @param $string
228
     *
229
     * @return mixed
230
     *
231
     * @throws \SoapFault
232
     */
233
    protected function encrypt($string)
234
    {
235
        $client = $this->createSoapClient($this->settings->apiUtilsUrl);
236
237
        $params = array(
238
            'aesKey' => $this->settings->key,
239
            'aesVector' => $this->settings->iv,
240
            'toBeEncrypted' => $string
241
        );
242
243
        $result = $client->EncryptInAES($params);
244
245
        return $result->EncryptInAESResult;
246
    }
247
248
    /**
249
     * Decrypt given string.
250
     *
251
     * @param $string
252
     *
253
     * @return mixed
254
     *
255
     * @throws \SoapFault
256
     */
257
    protected function decrypt($string)
258
    {
259
        $client = $this->createSoapClient($this->settings->apiUtilsUrl);
260
261
        $params = array(
262
            'aesKey' => $this->settings->key,
263
            'aesVector' => $this->settings->iv,
264
            'toBeDecrypted' => $string
265
        );
266
267
        $result = $client->DecryptInAES($params);
268
269
        return $result->DecryptInAESResult;
270
    }
271
272
    /**
273
     * create a new SoapClient
274
     *
275
     * @param $url
276
     *
277
     * @return \SoapClient
278
     *
279
     * @throws \SoapFault
280
     */
281
    protected function createSoapClient($url)
282
    {
283
        $opts = array(
284
            'ssl' => array(
285
                'verify_peer'=>false,
286
                'verify_peer_name'=>false
287
            )
288
        );
289
290
        $configs = array('stream_context' => stream_context_create($opts));
291
292
        return new \SoapClient($url, $configs);
293
    }
294
}
295