Passed
Push — master ( 7f24b0...bc42c3 )
by mahdi
03:07
created

Pasargad::request()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 14
c 0
b 0
f 0
dl 0
loc 25
rs 9.7998
cc 2
nc 2
nop 3
1
<?php
2
3
namespace Shetabit\Payment\Drivers\Pasargad;
4
5
use GuzzleHttp\Client;
6
use Shetabit\Payment\Invoice;
7
use Shetabit\Payment\Receipt;
8
use Shetabit\Payment\Abstracts\Driver;
9
use Shetabit\Payment\Contracts\ReceiptInterface;
10
use Shetabit\Payment\Exceptions\InvalidPaymentException;
11
use Shetabit\Payment\Drivers\Pasargad\Utils\RSAProcessor;
12
13
class Pasargad extends Driver
14
{
15
    /**
16
     * Guzzle client
17
     *
18
     * @var object
19
     */
20
    protected $client;
21
22
    /**
23
     * Invoice
24
     *
25
     * @var Invoice
26
     */
27
    protected $invoice;
28
29
    /**
30
     * Driver settings
31
     *
32
     * @var object
33
     */
34
    protected $settings;
35
36
    /**
37
     * Prepared invoice's data
38
     *
39
     * @var array
40
     */
41
    protected $preparedData = array();
42
43
    /**
44
     * Pasargad(PEP) constructor.
45
     * Construct the class with the relevant settings.
46
     *
47
     * @param Invoice $invoice
48
     * @param $settings
49
     */
50
    public function __construct(Invoice $invoice, $settings)
51
    {
52
        $this->invoice($invoice);
53
        $this->settings = (object) $settings;
54
        $this->client = new Client();
55
    }
56
57
    /**
58
     * Purchase Invoice.
59
     *
60
     * @return string
61
     */
62
    public function purchase()
63
    {
64
        $invoiceData = $this->getPreparedInvoiceData();
65
66
        $this->invoice->transactionId($invoiceData['InvoiceNumber']);
67
68
        // return the transaction's id
69
        return $this->invoice->getTransactionId();
70
    }
71
72
    /**
73
     * Pay the Invoice
74
     *
75
     * @return \Illuminate\Http\RedirectResponse|mixed
76
     */
77
    public function pay()
78
    {
79
        $paymentUrl = $this->settings->apiPaymentUrl;
80
        $getTokenUrl = $this->settings->apiGetToken;
81
        $tokenData = $this->request($getTokenUrl, $this->getPreparedInvoiceData());
82
83
        // redirect using HTML form
84
        return $this->redirectWithForm($paymentUrl, $tokenData, 'POST');
85
    }
86
87
    /**
88
     * Verify payment
89
     *
90
     * @return ReceiptInterface
91
     *
92
     * @throws InvalidPaymentException
93
     * @throws \GuzzleHttp\Exception\GuzzleException
94
     */
95
    public function verify() : ReceiptInterface
96
    {
97
        $invoiceDetails = $this->request(
98
            $this->settings->apiCheckTransactionUrl,
99
            [
100
                'TransactionReferenceID' => request()->input('tref')
101
            ]
102
        );
103
104
        $fields = [
105
            'MerchantCode' => $invoiceDetails['MerchantCode'],
106
            'TerminalCode' => $invoiceDetails['TerminalCode'],
107
            'InvoiceNumber' => $invoiceDetails['InvoiceNumber'],
108
            'InvoiceDate' => $invoiceDetails['InvoiceDate'],
109
            'Amount' => $invoiceDetails['Amount'],
110
            'Timestamp' => date("Y/m/d H:i:s"),
111
        ];
112
113
        $verifyResult = $this->request($this->settings->apiVerificationUrl, $fields);
114
115
        return $this->createReceipt($verifyResult, $invoiceDetails);
116
    }
117
118
    /**
119
     * Generate the payment's receipt
120
     *
121
     * @param $referenceId
122
     *
123
     * @return Receipt
124
     */
125
    protected function createReceipt($verifyResult, $invoiceDetails)
126
    {
127
        $referenceId = $invoiceDetails['TransactionReferenceID'];
128
        $traceNumber = $invoiceDetails['TraceNumber'];
129
        $referenceNumber = $invoiceDetails['ReferenceNumber'];
130
131
        $reciept = new Receipt('Pasargad', $referenceId);
132
133
        $reciept->detail('TraceNumber', $traceNumber);
134
        $reciept->detail('ReferenceNumber', $referenceNumber);
135
        $reciept->detail('MaskedCardNumber', $verifyResult['MaskedCardNumber']);
136
        $reciept->detail('ShaparakRefNumber', $verifyResult['ShaparakRefNumber']);
137
138
        return $reciept;
139
    }
140
141
    /**
142
     * A default message for exceptions
143
     *
144
     * @return string
145
     */
146
    protected function getDefaultExceptionMessage()
147
    {
148
        return 'مشکلی در دریافت اطلاعات از بانک به وجود آمده است';
149
    }
150
151
    /**
152
     * Sign given data.
153
     *
154
     * @param string $data
155
     *
156
     * @return string
157
     */
158
    public function sign($data)
159
    {
160
        $certificate = $this->settings->certificate;
161
        $certificateType = $this->settings->certificateType;
162
163
        $processor = new RSAProcessor($certificate, $certificateType);
164
165
        return $processor->sign($data);
166
    }
167
168
    /**
169
     * Retrieve prepared invoice's data
170
     *
171
     * @return array
172
     */
173
    protected function getPreparedInvoiceData()
174
    {
175
        if (empty($this->preparedData)) {
176
            $this->preparedData = $this->prepareInvoiceData();
177
        }
178
179
        return $this->preparedData;
180
    }
181
182
    /**
183
     * Prepare invoice data
184
     *
185
     * @return array
186
     */
187
    protected function prepareInvoiceData(): array
188
    {
189
        $action = 1003; // 1003 : for buy request (bank standard)
190
        $merchantCode = $this->settings->merchantId;
191
        $terminalCode = $this->settings->terminalCode;
192
        $amount = $this->invoice->getAmount(); //rial
193
        $redirectAddress = $this->settings->callbackUrl;
194
        $invoiceNumber = crc32($this->invoice->getUuid()) . rand(0, time());
195
        $timeStamp = date("Y/m/d H:i:s");
196
        $invoiceDate = date("Y/m/d H:i:s");
197
198
        if (!empty($this->invoice->getDetails()['date'])) {
199
            $invoiceDate = $this->invoice->getDetails()['date'];
200
        }
201
202
        return [
203
            'InvoiceNumber' => $invoiceNumber,
204
            'InvoiceDate' => $invoiceDate,
205
            'Amount' => $amount,
206
            'TerminalCode' => $terminalCode,
207
            'MerchantCode' => $merchantCode,
208
            'RedirectAddress' => $redirectAddress,
209
            'Timestamp' => $timeStamp,
210
            'Action' => $action,
211
        ];
212
    }
213
214
    /**
215
     * Prepare signature based on Pasargad document
216
     *
217
     * @param string $data
218
     * @return string
219
     */
220
    public function prepareSignature(string $data): string
221
    {
222
        return base64_encode($this->sign(sha1($data, true)));
223
    }
224
225
    /**
226
     * Make request to pasargad's Api
227
     *
228
     * @param string $url
229
     * @param array $body
230
     * @param string $method
231
     * @return array
232
     */
233
    protected function request(string $url, array $body, $method = 'POST'): 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

233
    protected function request(string $url, array $body, /** @scrutinizer ignore-unused */ $method = 'POST'): 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...
234
    {
235
        $body = json_encode($body);
236
        $sign = $this->prepareSignature($body);
237
238
        $response = $this->client->request(
239
            'POST',
240
            $url,
241
            [
242
                'body' => $body,
243
                'headers' => [
244
                    'content-type' => 'application/json',
245
                    'Sign' => $sign
246
                ],
247
                "http_errors" => false,
248
            ]
249
        );
250
251
        $result = json_decode($response->getBody(), true);
252
253
        if ($result['IsSuccess'] === false) {
254
            throw new InvalidPaymentException($result['Message']);
255
        }
256
257
        return $result;
258
    }
259
}
260