Test Failed
Pull Request — master (#256)
by
unknown
02:44
created

Pasargad::createToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 13
rs 10
1
<?php
2
3
namespace Shetabit\Multipay\Drivers\Pasargad;
4
5
use GuzzleHttp\Client;
6
use GuzzleHttp\Exception\GuzzleException;
7
use PHPUnit\Util\Exception;
8
use Shetabit\Multipay\Drivers\Pasargad\Pasargadholder\Pasargadholder;
0 ignored issues
show
Bug introduced by
The type Shetabit\Multipay\Driver...adholder\Pasargadholder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
9
use Shetabit\Multipay\Invoice;
10
use Shetabit\Multipay\Receipt;
11
use Shetabit\Multipay\Abstracts\Driver;
12
use Shetabit\Multipay\Contracts\ReceiptInterface;
13
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
14
use Shetabit\Multipay\Drivers\Pasargad\Utils\RSAProcessor;
0 ignored issues
show
Bug introduced by
The type Shetabit\Multipay\Driver...rgad\Utils\RSAProcessor was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use Shetabit\Multipay\RedirectionForm;
16
use Shetabit\Multipay\Request;
17
use DateTimeZone;
18
use DateTime;
19
20
class Pasargad extends Driver
21
{
22
    /**
23
     * Guzzle client
24
     *
25
     * @var object
26
     */
27
    protected $client;
28
29
    /**
30
     * Invoice
31
     *
32
     * @var Invoice
33
     */
34
    protected $invoice;
35
36
    /**
37
     * Driver settings
38
     *
39
     * @var object
40
     */
41
    protected $settings;
42
43
    /**
44
     * Prepared invoice's data
45
     *
46
     * @var array
47
     */
48
    protected $preparedData = array();
49
50
    /**
51
     * Pasardad Holder
52
     * @var string
53
     */
54
    protected $holder;
55
56
    /**
57
     * Pasargad(PEP) constructor.
58
     * Construct the class with the relevant settings.
59
     *
60
     * @param Invoice $invoice
61
     * @param $settings
62
     */
63
    public function __construct(Invoice $invoice, $settings)
64
    {
65
        $this->invoice($invoice);
66
        $this->settings = (object)$settings;
67
        $this->client = new Client();
68
        $this->holder = new Pasargadholder();
69
    }
70
71
    /**
72
     * Purchase Invoice.
73
     *
74
     * @return string
75
     * @throws InvalidPaymentException
76
     */
77
    public function purchase(): string
78
    {
79
        $invoiceData = $this->getPreparedInvoiceData();
80
81
        $this->invoice->transactionId($invoiceData['invoice']);
82
83
        $response = $this->request(
84
            $this->settings->apiPaymentUrl,
85
            $invoiceData,
86
            'POST',
87
            $this->createToken()
88
        );
89
90
        $response['data']['urlId'] ? $this->holder->urlId($response['data']['urlId']) :
91
            throw  new InvalidPaymentException("urlId is not set.");
92
93
94
        return $this->invoice->getTransactionId();
95
    }
96
97
    /**
98
     * Pay the Invoice
99
     *
100
     * @return RedirectionForm
101
     */
102
    public function pay(): RedirectionForm
103
    {
104
        $paymentUrl = $this->settings->apiBaseUrl . $this->holder->getUrlId();
105
        
106
        $data = [
107
            'Token' => $this->holder->getUrlId(),
108
            'TransactionId' => $this->invoice->getTransactionId()
109
        ];
110
111
        // redirect using HTML form
112
        return $this->redirectWithForm($paymentUrl, $data, "POST");
113
    }
114
115
    /**
116
     * Verify payment
117
     *
118
     * @return ReceiptInterface
119
     *
120
     * @throws InvalidPaymentException
121
     * @throws \Exception
122
     */
123
    public function verify(): ReceiptInterface
124
    {
125
        $transactionId = $this->invoice->getTransactionId();
126
        $urlId = $this->holder->getUrlId();
127
128
        $verifyResult = $this->request($this->settings->verifyPayment, [
129
            'invoice' => $transactionId,
130
            'urlId' => $urlId
131
        ]);
132
133
        $invoiceId = $verifyResult['data']['invoiceId'];
134
135
        $receipt =  $this->createReceipt($invoiceId);
136
137
        $receipt->detail([
138
            'resultMsg' => $verifyResult['resultCode'],
139
            'resultMsg' => $verifyResult['resultMsg'] ?? null,
140
            'hashedCardNumber' => $verifyResult['data']['hashedCardNumber'] ?? null,
141
            'maskedCardNumber' => $verifyResult['data']['maskedCardNumber'] ?? null,
142
            'invoiceId' => $invoiceId,
143
            'referenceNumber' =>  $verifyResult['data']['maskedCardNumber'] ?? null,
144
            'trackId' =>  $verifyResult['data']['trackId'] ?? null,
145
            'amount' =>  $verifyResult['data']['amount'] ?? null,
146
            'requestDate' => $verifyResult['data']['requestDate'] ?? null,
147
        ]);
148
149
        return $receipt;
150
    }
151
152
    /**
153
     * Generate the payment's receipt
154
     *
155
     * @param $verifyResult
156
     * @param $invoiceDetails
157
     * @return Receipt
158
     */
159
    protected function createReceipt($referenceId): Receipt
160
    {
161
        return new Receipt('pasargad', $referenceId);
162
    }
163
164
    /**
165
     * Retrieve prepared invoice's data
166
     *
167
     * @return array
168
     */
169
    protected function getPreparedInvoiceData(): array
170
    {
171
        if (empty($this->preparedData)) {
172
            $this->preparedData = $this->prepareInvoiceData();
173
        }
174
175
        return $this->preparedData;
176
    }
177
178
    /**
179
     * Prepare invoice data
180
     *
181
     * @return array
182
     * @throws \Exception
183
     */
184
    protected function prepareInvoiceData(): array
185
    {
186
        $action = 8; // 8 : for buy request (bank standard)
187
        $terminalCode = $this->settings->terminalCode;
188
        $amount = $this->invoice->getAmount();
189
        $redirectAddress = $this->settings->callbackUrl;
190
        $invoiceNumber = crc32($this->invoice->getUuid()) . rand(0, time());
191
192
        $iranTime = new DateTime('now', new DateTimeZone('Asia/Tehran'));
193
        $invoiceDate = $iranTime->format("Y/m/d H:i:s");
194
195
        if (!empty($this->invoice->getDetails()['date'])) {
196
            $invoiceDate = $this->invoice->getDetails()['date'];
197
        }
198
199
        return [
200
            'invoice' => $invoiceNumber,
201
            'invoiceDate' => $invoiceDate,
202
            'amount' => $amount,
203
            'terminalNumber' => $terminalCode,
204
            'callbackApi' => $redirectAddress,
205
            'serviceCode' => $action,
206
            'nationalCode' => "",
207
            'serviceType' => "PURCHASE",
208
            'mobileNumber' => ""
209
        ];
210
    }
211
212
    /**
213
     * Make request to pasargad's Api
214
     *
215
     * @param string $url
216
     * @param array $body
217
     * @param string $method
218
     * @param string|null $token
219
     * @return array
220
     * @throws GuzzleException
221
     * @throws InvalidPaymentException
222
     */
223
    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

223
    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...
224
    {
225
        $body = json_encode($body);
226
        $token = $token != null ? 'Bearer '.$token : null;
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $token of type null|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
227
228
        $response = $this->client->request(
229
            'POST',
230
            $url,
231
            [
232
                'body' => $body,
233
                'headers' => [
234
                    'content-type' => 'application/json',
235
                    'Authorization' => $token
236
                ],
237
                "http_errors" => false,
238
            ]
239
        );
240
241
        $result = json_decode($response->getBody(), true);
242
243
        if ($result['resultMsg'] !== 'Successful') {
244
            throw new InvalidPaymentException($result['resultMsg']);
245
        }
246
247
        return $result;
248
    }
249
250
    /**
251
     * * make token with username and password
252
     * @return string
253
     */
254
    protected function createToken(): string
255
    {
256
        $data = [
257
            "username" => $this->settings->username,
258
            "password" => $this->settings->password
259
        ];
260
261
        $getTokenUrl = $this->settings->apiGetToken;
262
263
        return $this->request(
264
            $getTokenUrl,
265
            $data
266
        )['token'];
267
    }
268
}
269