Passed
Pull Request — master (#32)
by
unknown
02:04
created

Payment::resetCallbackUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 5
rs 10
1
<?php
2
3
namespace Shetabit\Multipay;
4
5
use Shetabit\Multipay\Contracts\DriverInterface;
6
use Shetabit\Multipay\Contracts\ReceiptInterface;
7
use Shetabit\Multipay\Exceptions\DriverNotFoundException;
8
use Shetabit\Multipay\Exceptions\InvoiceNotFoundException;
9
use Shetabit\Multipay\Traits\HasPaymentEvents;
10
use Shetabit\Multipay\Traits\InteractsWithRedirectionForm;
11
12
class Payment
13
{
14
    use InteractsWithRedirectionForm;
15
    use HasPaymentEvents;
16
17
    /**
18
     * Payment Configuration.
19
     *
20
     * @var array
21
     */
22
    protected $config;
23
24
    /**
25
     * Payment Driver Settings.
26
     *
27
     * @var array
28
     */
29
    protected $settings;
30
31
    /**
32
     * callbackUrl
33
     *
34
     * @var string
35
     */
36
    protected $callbackUrl;
37
38
    /**
39
     * Payment Driver Name.
40
     *
41
     * @var string
42
     */
43
    protected $driver;
44
45
    /**
46
     * Payment Driver Instance.
47
     *
48
     * @var object
49
     */
50
    protected $driverInstance;
51
52
    /**
53
     * @var Invoice
54
     */
55
    protected $invoice;
56
57
    /**
58
     * PaymentManager constructor.
59
     *
60
     * @param array $config
61
     *
62
     * @throws \Exception
63
     */
64
    public function __construct(array $config = [])
65
    {
66
        $this->config = empty($config) ? $this->loadDefaultConfig() : $config;
67
        $this->invoice(new Invoice());
68
        $this->via($this->config['default']);
69
    }
70
71
    /**
72
     * Retrieve Default config's path.
73
     *
74
     * @return string
75
     */
76
    public static function getDefaultConfigPath() : string
77
    {
78
        return dirname(__DIR__).'/config/payment.php';
79
    }
80
81
    /**
82
     * Set custom configs
83
     * we can use this method when we want to use dynamic configs
84
     *
85
     * @param $key
86
     * @param $value|null
87
     *
88
     * @return $this
89
     */
90
    public function config($key, $value = null)
91
    {
92
        $configs = [];
93
94
        $key = is_array($key) ? $key : [$key => $value];
95
96
        foreach ($key as $k => $v) {
97
            $configs[$k] = $v;
98
        }
99
100
        $this->settings = array_merge($this->settings, $configs);
101
102
        return $this;
103
    }
104
105
    /**
106
     * Set callbackUrl.
107
     *
108
     * @param $url|null
109
     * @return $this
110
     */
111
    public function callbackUrl($url = null)
112
    {
113
        $this->callbackUrl = $url;
114
115
        return $this;
116
    }
117
118
    /**
119
     * Reset the callbackUrl to its original that exists in configs.
120
     *
121
     * @return $this
122
     */
123
    public function resetCallbackUrl()
124
    {
125
        $this->callbackUrl();
126
127
        return $this;
128
    }
129
130
    /**
131
     * Set payment amount.
132
     *
133
     * @param $amount
134
     * @return $this
135
     * @throws \Exception
136
     */
137
    public function amount($amount)
138
    {
139
        $this->invoice->amount($amount);
140
141
        return $this;
142
    }
143
144
    /**
145
     * Set a piece of data to the details.
146
     *
147
     * @param $key
148
     *
149
     * @param $value|null
150
     *
151
     * @return $this
152
     */
153
    public function detail($key, $value = null)
154
    {
155
        $this->invoice->detail($key, $value);
156
157
        return $this;
158
    }
159
160
    /**
161
     * Set transaction's id
162
     *
163
     * @param $id
164
     *
165
     * @return $this
166
     */
167
    public function transactionId($id)
168
    {
169
        $this->invoice->transactionId($id);
170
171
        return $this;
172
    }
173
174
    /**
175
     * Change the driver on the fly.
176
     *
177
     * @param $driver
178
     *
179
     * @return $this
180
     *
181
     * @throws \Exception
182
     */
183
    public function via($driver)
184
    {
185
        $this->driver = $driver;
186
        $this->validateDriver();
187
        $this->invoice->via($driver);
188
        $this->settings = $this->config['drivers'][$driver];
189
190
        return $this;
191
    }
192
193
    /**
194
     * Purchase the invoice
195
     *
196
     * @param Invoice $invoice|null
197
     * @param $finalizeCallback|null
198
     *
199
     * @return $this
200
     *
201
     * @throws \Exception
202
     */
203
    public function purchase(Invoice $invoice = null, $finalizeCallback = null)
204
    {
205
        if ($invoice) { // create new invoice
206
            $this->invoice($invoice);
207
        }
208
209
        $this->driverInstance = $this->getFreshDriverInstance();
210
211
        //purchase the invoice
212
        $transactionId = $this->driverInstance->purchase();
213
        if ($finalizeCallback) {
214
            call_user_func_array($finalizeCallback, [$this->driverInstance, $transactionId]);
215
        }
216
217
        // dispatch event
218
        $this->dispatchEvent(
219
            'purchase',
220
            $this->driverInstance,
221
            $this->driverInstance->getInvoice()
222
        );
223
224
        return $this;
225
    }
226
227
    /**
228
     * Call custome function .
229
     *
230
     * @param $method
231
     *
232
     * @return $data
0 ignored issues
show
Documentation Bug introduced by
The doc comment $data at position 0 could not be parsed: Unknown type name '$data' at position 0 in $data.
Loading history...
233
     *
234
     */
235
    public function call($method , $data = array())
236
    {
237
        $this->driverInstance = $this->getFreshDriverInstance();
238
        $result = $this->driverInstance->call($method, $data);
239
        return $result;
240
    }
241
242
    /**
243
     * Pay the purchased invoice.
244
     *
245
     * @param $initializeCallback|null
246
     *
247
     * @return mixed
248
     *
249
     * @throws \Exception
250
     */
251
    public function pay($initializeCallback = null)
252
    {
253
        $this->driverInstance = $this->getDriverInstance();
254
255
        if ($initializeCallback) {
256
            call_user_func($initializeCallback, $this->driverInstance);
257
        }
258
259
        $this->validateInvoice();
260
261
        // dispatch event
262
        $this->dispatchEvent(
263
            'pay',
264
            $this->driverInstance,
265
            $this->driverInstance->getInvoice()
266
        );
267
268
        return $this->driverInstance->pay();
269
    }
270
271
    /**
272
     * Verifies the payment
273
     *
274
     * @param $finalizeCallback|null
275
     *
276
     * @return ReceiptInterface
277
     *
278
     * @throws InvoiceNotFoundException
279
     */
280
    public function verify($finalizeCallback = null) : ReceiptInterface
281
    {
282
        $this->driverInstance = $this->getDriverInstance();
283
        $this->validateInvoice();
284
        $receipt = $this->driverInstance->verify();
285
286
        if (!empty($finalizeCallback)) {
287
            call_user_func($finalizeCallback, $receipt, $this->driverInstance);
288
        }
289
290
        // dispatch event
291
        $this->dispatchEvent(
292
            'verify',
293
            $receipt,
294
            $this->driverInstance,
295
            $this->driverInstance->getInvoice()
296
        );
297
298
        return $receipt;
299
    }
300
301
    /**
302
     * Retrieve default config.
303
     *
304
     * @return array
305
     */
306
    protected function loadDefaultConfig() : array
307
    {
308
        return require(static::getDefaultConfigPath());
309
    }
310
311
    /**
312
     * Set invoice instance.
313
     *
314
     * @param Invoice $invoice
315
     *
316
     * @return self
317
     */
318
    protected function invoice(Invoice $invoice)
319
    {
320
        $this->invoice = $invoice;
321
322
        return $this;
323
    }
324
325
    /**
326
     * Retrieve current driver instance or generate new one.
327
     *
328
     * @return mixed
329
     * @throws \Exception
330
     */
331
    protected function getDriverInstance()
332
    {
333
        if (!empty($this->driverInstance)) {
334
            return $this->driverInstance;
335
        }
336
337
        return $this->getFreshDriverInstance();
338
    }
339
340
    /**
341
     * Get new driver instance
342
     *
343
     * @return mixed
344
     * @throws \Exception
345
     */
346
    protected function getFreshDriverInstance()
347
    {
348
        $this->validateDriver();
349
        $class = $this->config['map'][$this->driver];
350
351
        if (!empty($this->callbackUrl)) { // use custom callbackUrl if exists
352
            $this->settings['callbackUrl'] = $this->callbackUrl;
353
        }
354
355
        return new $class($this->invoice, $this->settings);
356
    }
357
358
    /**
359
     * Validate Invoice.
360
     *
361
     * @throws InvoiceNotFoundException
362
     */
363
    protected function validateInvoice()
364
    {
365
        if (empty($this->invoice)) {
366
            throw new InvoiceNotFoundException('Invoice not selected or does not exist.');
367
        }
368
    }
369
370
    /**
371
     * Validate driver.
372
     *
373
     * @throws \Exception
374
     */
375
    protected function validateDriver()
376
    {
377
        if (empty($this->driver)) {
378
            throw new DriverNotFoundException('Driver not selected or default driver does not exist.');
379
        }
380
381
        if (empty($this->config['drivers'][$this->driver]) || empty($this->config['map'][$this->driver])) {
382
            throw new DriverNotFoundException('Driver not found in config file. Try updating the package.');
383
        }
384
385
        if (!class_exists($this->config['map'][$this->driver])) {
386
            throw new DriverNotFoundException('Driver source not found. Please update the package.');
387
        }
388
389
        $reflect = new \ReflectionClass($this->config['map'][$this->driver]);
390
391
        if (!$reflect->implementsInterface(DriverInterface::class)) {
392
            throw new \Exception("Driver must be an instance of Contracts\DriverInterface.");
393
        }
394
    }
395
}
396