Passed
Pull Request — master (#259)
by
unknown
02:47
created

NovinoPay::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 5
rs 10
1
<?php
2
/*
3
 * @Author: Arvin Loripour - ViraEcosystem 
4
 * @Date: 2024-08-18 21:52:23 
5
 * Copyright by Arvin Loripour 
6
 * WebSite : http://www.arvinlp.ir 
7
 * @Last Modified by:   Arvin.Loripour 
8
 * @Last Modified time: 2024-08-18 21:52:23 
9
 */
10
11
namespace Shetabit\Multipay\Drivers\NovinoPay;
12
13
use GuzzleHttp\Client;
14
use Shetabit\Multipay\Abstracts\Driver;
15
use Shetabit\Multipay\Exceptions\InvalidPaymentException;
16
use Shetabit\Multipay\Exceptions\PurchaseFailedException;
17
use Shetabit\Multipay\Contracts\ReceiptInterface;
18
use Shetabit\Multipay\Invoice;
19
use Shetabit\Multipay\Receipt;
20
use Shetabit\Multipay\RedirectionForm;
21
use Shetabit\Multipay\Request;
22
23
class NovinoPay extends Driver
24
{
25
    /**
26
     * Novinopay Client.
27
     *
28
     * @var object
29
     */
30
    protected $client;
31
32
    /**
33
     * Invoice
34
     *
35
     * @var Invoice
36
     */
37
    protected $invoice;
38
39
    /**
40
     * Driver settings
41
     *
42
     * @var object
43
     */
44
    protected $settings;
45
46
    /**
47
     * Novinopay constructor.
48
     * Construct the class with the relevant settings.
49
     *
50
     * @param Invoice $invoice
51
     * @param $settings
52
     */
53
    public function __construct(Invoice $invoice, $settings)
54
    {
55
        $this->invoice($invoice);
56
        $this->settings = (object) $settings;
57
        $this->client = new Client();
58
    }
59
60
    /**
61
     * Purchase Invoice.
62
     *
63
     * @return string
64
     *
65
     * @throws \GuzzleHttp\Exception\GuzzleException
66
     */
67
    public function purchase()
68
    {
69
        $details = $this->invoice->getDetails();
70
71
        $amount = $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 10 : 1); // convert to rial
72
73
        $orderId = crc32($this->invoice->getUuid()).time();
0 ignored issues
show
Unused Code introduced by
The assignment to $orderId is dead and can be removed.
Loading history...
74
        if (!empty($details['orderId'])) {
75
            $orderId = $details['orderId'];
76
        } elseif (!empty($details['order_id'])) {
77
            $orderId = $details['order_id'];
78
        }
79
        
80
        $data = array(
81
            "merchant_id"=> $this->settings->merchantId, //required
82
            "callback_url"=> $this->settings->callbackUrl, //required
83
            "amount"=> $amount, //required
84
        );
85
86
        // Pass current $data array to add existing optional details
87
        $data = $this->checkOptionalDetails($data);
88
89
        $response = $this->client->request(
90
            'POST',
91
            $this->settings->apiPurchaseUrl,
92
            ["json" => $data, "http_errors" => false]
93
        );
94
95
        $body = json_decode($response->getBody()->getContents(), false);
96
        
97
        if ($body->status != 100) {
98
            // some error has happened
99
            throw new PurchaseFailedException($body->message);
100
        }
101
102
        $this->invoice->transactionId($body->data->authority);
103
104
        // return the transaction's id
105
        return $this->invoice->getTransactionId();
106
    }
107
108
    /**
109
     * Pay the Invoice
110
     *
111
     * @return RedirectionForm
112
     */
113
    public function pay() : RedirectionForm
114
    {
115
        $payUrl = $this->settings->apiPaymentUrl.$this->invoice->getTransactionId();
116
117
        return $this->redirectWithForm($payUrl);
118
    }
119
120
    /**
121
     * Verify payment
122
     *
123
     * @return mixed|void
124
     *
125
     * @throws InvalidPaymentException
126
     * @throws \GuzzleHttp\Exception\GuzzleException
127
     */
128
    public function verify() : ReceiptInterface
129
    {
130
        $successFlag = Request::input('PaymentStatus');
131
        $status = Request::input('status');
0 ignored issues
show
Unused Code introduced by
The assignment to $status is dead and can be removed.
Loading history...
132
        $orderId = Request::input('InvoiceID');
0 ignored issues
show
Unused Code introduced by
The assignment to $orderId is dead and can be removed.
Loading history...
133
        $transactionId = $this->invoice->getTransactionId() ?? Request::input('Authority');
134
135
        if ($successFlag != "NOK") {
136
            $this->notVerified('انصراف از پرداخت', 0);
137
        }
138
139
        //start verfication
140
        $data = array(
141
            "merchant_id" => $this->settings->merchantId, //required
142
            "authority" => $transactionId, //required
143
            'amount' => $this->invoice->getAmount() * ($this->settings->currency == 'T' ? 1 : 10), // convert to rial
144
        );
145
146
        $response = $this->client->request(
147
            'POST',
148
            $this->settings->apiVerificationUrl,
149
            ["json" => $data, "http_errors" => false]
150
        );
151
152
        $body = json_decode($response->getBody()->getContents(), false);
153
154
        if ($body->status != 100) {
155
            $this->notVerified($body->message, $body->status);
156
        }
157
158
        /*
159
            for more info:
160
            var_dump($body);
161
        */
162
163
        return $this->createReceipt($body->data->ref_id);
164
    }
165
166
    /**
167
     * Generate the payment's receipt
168
     *
169
     * @param $referenceId
170
     *
171
     * @return Receipt
172
     */
173
    protected function createReceipt($referenceId)
174
    {
175
        $receipt = new Receipt('Novinopay', $referenceId);
176
177
        return $receipt;
178
    }
179
180
    private function translateStatus($status)
0 ignored issues
show
Unused Code introduced by
The method translateStatus() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
181
    {
182
        $translations = [
183
            'NOK' => 'انصراف از پرداخت',
184
        ];
185
186
        $unknownError = 'خطای ناشناخته ای رخ داده است.';
187
188
        return array_key_exists($status, $translations) ? $translations[$status] : $unknownError;
189
    }
190
191
    /**
192
     * Trigger an exception
193
     *
194
     * @param $message
195
     * @throws InvalidPaymentException
196
     */
197
    private function notVerified($message, $code = 0)
198
    {
199
        if (empty($message)) {
200
            throw new InvalidPaymentException('خطای ناشناخته ای رخ داده است.', $code);
201
        } else {
202
            throw new InvalidPaymentException($message, $code);
203
        }
204
    }
205
206
    /**
207
     * Retrieve data from details using its name.
208
     *
209
     * @return string
210
     */
211
    private function extractDetails($name)
212
    {
213
        $detail = null;
214
        if (!empty($this->invoice->getDetails()[$name])) {
215
            $detail = $this->invoice->getDetails()[$name];
216
        } elseif (!empty($this->settings->$name)) {
217
            $detail = $this->settings->$name;
218
        }
219
220
        return $detail;
221
    }
222
223
    /**
224
     * Checks optional parameters existence (except orderId) and
225
     * adds them to the given $data array and returns new array
226
     * with optional parameters for api call.
227
     *
228
     * To avoid errors and have a cleaner api call log, `null`
229
     * parameters are not sent.
230
     *
231
     * To add new parameter support in the future, all that
232
     * is needed is to add parameter name to $optionalParameters
233
     * array.
234
     *
235
     * @param $data
236
     *
237
     * @return array
238
     */
239
    private function checkOptionalDetails($data)
240
    {
241
        $optionalParameters = [
242
            'mobile',
243
            'description',
244
            'allowedCards',
245
            'feeMode',
246
            'percentMode',
247
            'multiplexingInfos'
248
        ];
249
250
        foreach ($optionalParameters as $parameter) {
251
            if (!is_null($this->extractDetails($parameter))) {
252
                $parameterArray = array(
253
                    $parameter => $this->extractDetails($parameter)
254
                );
255
                $data = array_merge($data, $parameterArray);
256
            }
257
        }
258
259
        return $data;
260
    }
261
}
262