Passed
Pull Request — master (#256)
by
unknown
02:40
created

Pasargad::prepareSignature()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\Pasargad;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\GuzzleException;
7
use Shetabit\Multipay\Drivers\Pasargad\PasargadHolder\PasargadHolder;
8
use Shetabit\Multipay\Invoice;
9
use Shetabit\Multipay\Receipt;
10
use Shetabit\Multipay\Abstracts\Driver;
11
use Shetabit\Multipay\Contracts\ReceiptInterface;
12
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
13
use Shetabit\Multipay\RedirectionForm;
14
use DateTimeZone;
15
use DateTime;
16
17
class Pasargad extends Driver
18
{
19
    /**
20
     * Guzzle client
21
     *
22
     * @var object
23
     */
24
    protected $client;
25
26
    /**
27
     * Invoice
28
     *
29
     * @var Invoice
30
     */
31
    protected $invoice;
32
33
    /**
34
     * Driver settings
35
     *
36
     * @var object
37
     */
38
    protected $settings;
39
40
    /**
41
     * Prepared invoice's data
42
     *
43
     * @var array
44
     */
45
    protected $preparedData = array();
46
47
    /**
48
     * Pasardad Holder
49
     * @var string
50
     */
51
    protected $holder;
52
53
    /**
54
     * Pasargad(PEP) constructor.
55
     * Construct the class with the relevant settings.
56
     *
57
     * @param Invoice $invoice
58
     * @param $settings
59
     */
60
    public function __construct(Invoice $invoice, $settings)
61
    {
62
        $this->invoice($invoice);
63
        $this->settings = (object)$settings;
64
        $this->client = new Client();
65
        $this->holder = new PasargadHolder();
0 ignored issues
show
Documentation Bug introduced by
It seems like new Shetabit\Multipay\Dr...Holder\PasargadHolder() of type Shetabit\Multipay\Driver...adHolder\PasargadHolder is incompatible with the declared type string of property $holder.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
66
    }
67
68
    /**
69
     * Purchase Invoice.
70
     *
71
     * @return string
72
     * @throws InvalidPaymentException
73
     * @throws GuzzleException
74
     * @throws \Exception
75
     */
76
    public function purchase(): string
77
    {
78
        $invoiceData = $this->getPreparedInvoiceData();
79
80
        $this->invoice->transactionId($invoiceData['invoice']);
81
82
        $response = $this->request(
83
            $this->settings->apiPaymentUrl,
84
            $invoiceData,
85
            'POST',
86
            $this->createToken()
87
        );
88
89
        if ($response['data']['urlId']) {
90
            $this->holder->urlId($response['data']['urlId']);
91
        } else {
92
            throw new InvalidPaymentException("urlId is not set.");
93
        }
94
95
        return $this->invoice->getTransactionId();
96
    }
97
98
    /**
99
     * Pay the Invoice
100
     *
101
     * @return RedirectionForm
102
     */
103
    public function pay(): RedirectionForm
104
    {
105
        $paymentUrl = $this->settings->apiBaseUrl . $this->holder->getUrlId();
106
107
        // redirect using HTML form
108
        return $this->redirectWithForm($paymentUrl, ['Token' => $this->holder->getUrlId()]);
109
    }
110
111
    /**
112
     * Verify payment
113
     *
114
     * @return ReceiptInterface
115
     *
116
     * @throws InvalidPaymentException
117
     * @throws \Exception
118
     * @throws GuzzleException
119
     */
120
    public function verify(): ReceiptInterface
121
    {
122
123
        $transactionId = $this->invoice->getTransactionId();
124
125
        $payment_inquiry = $this->request(
126
            $this->settings->paymentInquiry,
127
            ['invoiceId' => $transactionId],
128
            'POST',
129
            $this->createToken()
130
        );
131
132
        if ($payment_inquiry['resultCode'] != 0) {
133
            throw new InvalidPaymentException("This transaction is fail.");
134
        }
135
136
        if($payment_inquiry['data']['transactionId'] !== $transactionId) {
137
            throw new InvalidPaymentException("This transaction is fail.");
138
        }
139
140
        $verifyResult = $this->request(
141
            $this->settings->verifyPayment,
142
            [
143
                'invoice' => $transactionId,
144
                'urlId' => $payment_inquiry['data']['url']
145
            ],
146
            'POST',
147
            $this->createToken()
148
        );
149
150
        if (!$verifyResult['data']['referenceNumber']) {
151
            throw new InvalidPaymentException("This transaction is fail.");
152
        }
153
154
        $receipt =  $this->createReceipt($$verifyResult['data']['referenceNumber']);
155
156
        $receipt->detail([
157
            'resultCode' => $verifyResult['resultCode'],
158
            'resultMsg' => $verifyResult['resultMsg'] ?? null,
159
            'hashedCardNumber' => $verifyResult['data']['hashedCardNumber'] ?? null,
160
            'maskedCardNumber' => $verifyResult['data']['maskedCardNumber'] ?? null,
161
            'invoiceId' => $transactionId,
162
            'referenceNumber' =>  $verifyResult['data']['referenceNumber'] ?? null,
163
            'trackId' =>  $verifyResult['data']['trackId'] ?? null,
164
            'amount' =>  $verifyResult['data']['amount'] ?? null,
165
            'requestDate' => $verifyResult['data']['requestDate'] ?? null,
166
        ]);
167
168
        return $receipt;
169
    }
170
171
172
    /**
173
     * Generate the payment's receipt
174
     *
175
     * @param $referenceId
176
     * @return Receipt
177
     */
178
    protected function createReceipt($referenceId): Receipt
179
    {
180
        return new Receipt('pasargad', $referenceId);
181
    }
182
183
    /**
184
     * Retrieve prepared invoice's data
185
     *
186
     * @return array
187
     * @throws \Exception
188
     */
189
    protected function getPreparedInvoiceData(): array
190
    {
191
        if (empty($this->preparedData)) {
192
            $this->preparedData = $this->prepareInvoiceData();
193
        }
194
195
        return $this->preparedData;
196
    }
197
198
    /**
199
     * Prepare invoice data
200
     *
201
     * @return array
202
     * @throws \Exception
203
     */
204
    protected function prepareInvoiceData(): array
205
    {
206
        $action = 8; // 8 : for buy request (bank standard)
207
        $terminalCode = $this->settings->terminalCode;
208
        $amount = $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 10 : 1);
209
        $redirectAddress = $this->settings->callbackUrl;
210
        $invoiceNumber = crc32($this->invoice->getUuid()) . rand(0, time());
211
212
        $iranTime = new DateTime('now', new DateTimeZone('Asia/Tehran'));
213
        $invoiceDate = $iranTime->format("Y/m/d H:i:s");
214
215
        if (!empty($this->invoice->getDetails()['date'])) {
216
            $invoiceDate = $this->invoice->getDetails()['date'];
217
        }
218
219
        return [
220
            'invoice' => $invoiceNumber,
221
            'invoiceDate' => $invoiceDate,
222
            'amount' => $amount,
223
            'terminalNumber' => $terminalCode,
224
            'callbackApi' => $redirectAddress,
225
            'serviceCode' => $action,
226
            'nationalCode' => "",
227
            'serviceType' => "PURCHASE",
228
            'mobileNumber' => ""
229
        ];
230
    }
231
232
    /**
233
     * Make request to pasargad's Api
234
     *
235
     * @param string $url
236
     * @param array $body
237
     * @param string $method
238
     * @param string|null $token
239
     * @return array
240
     * @throws GuzzleException
241
     * @throws InvalidPaymentException
242
     */
243
    protected function request(string $url, array $body, string $method = 'POST', string $token = null): array
0 ignored issues
show
Unused Code introduced by
The parameter $method is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

243
    protected function request(string $url, array $body, /** @scrutinizer ignore-unused */ string $method = 'POST', string $token = null): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
244
    {
245
        $body = json_encode($body);
246
        $token = $token !== null ? 'Bearer '.$token : null;
247
248
        $response = $this->client->request(
249
            'POST',
250
            $url,
251
            [
252
                'body' => $body,
253
                'headers' => [
254
                    'content-type' => 'application/json',
255
                    'Authorization' => $token
256
                ],
257
                "http_errors" => false,
258
            ]
259
        );
260
261
        $result = json_decode($response->getBody(), true);
262
263
        if ($result['resultMsg'] !== 'Successful') {
264
            throw new InvalidPaymentException($result['resultMsg']);
265
        }
266
267
        return $result;
268
    }
269
270
    /**
271
     * * make token with username and password
272
     * @return string
273
     * @throws InvalidPaymentException
274
     */
275
    protected function createToken(): string
276
    {
277
        $data = [
278
            "username" => $this->settings->username,
279
            "password" => $this->settings->password
280
        ];
281
282
        $getTokenUrl = $this->settings->apiGetToken;
283
284
        try {
285
            return $this->request($getTokenUrl, $data)['token'];
286
        } catch (GuzzleException|InvalidPaymentException $e) {
287
            throw new InvalidPaymentException($e->getMessage());
288
        }
289
    }
290
}
291