Passed
Pull Request — master (#37)
by
unknown
02:50
created

PaymentManager::description()   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
eloc 2
c 1
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Shetabit\Payment;
4
5
use Shetabit\Payment\Contracts\DriverInterface;
6
use Shetabit\Payment\Contracts\ReceiptInterface;
7
use Shetabit\Payment\Events\InvoicePurchasedEvent;
8
use Shetabit\Payment\Events\InvoiceVerifiedEvent;
9
use Shetabit\Payment\Exceptions\DriverNotFoundException;
10
use Shetabit\Payment\Exceptions\InvoiceNotFoundException;
11
12
class PaymentManager
13
{
14
    /**
15
     * Payment Configuration.
16
     *
17
     * @var array
18
     */
19
    protected $config;
20
21
    /**
22
     * Payment Driver Settings.
23
     *
24
     * @var array
25
     */
26
    protected $settings;
27
28
    /**
29
     * callbackUrl
30
     *
31
     * @var string
32
     */
33
    protected $callbackUrl;
34
35
    /**
36
     * Payment Driver Name.
37
     *
38
     * @var string
39
     */
40
    protected $driver;
41
42
    /**
43
     * Payment Driver Instance.
44
     *
45
     * @var object
46
     */
47
    protected $driverInstance;
48
49
    /**
50
     * @var Invoice
51
     */
52
    protected $invoice;
53
54
    /**
55
     * PaymentManager constructor.
56
     *
57
     * @param $config
58
     * @throws \Exception
59
     */
60
    public function __construct($config)
61
    {
62
        $this->config = $config;
63
        $this->invoice(new Invoice());
64
        $this->via($this->config['default']);
65
    }
66
67
    /**
68
     * Set custom configs
69
     * we can use this method when we want to use dynamic configs
70
     *
71
     * @param $key
72
     * @param $value|null
73
     * @return $this
74
     */
75
    public function config($key, $value = null)
76
    {
77
        $configs = [];
78
79
        $key = is_array($key) ? $key : [$key => $value];
80
81
        foreach ($key as $k => $v) {
82
            $configs[$k] = $v;
83
        }
84
85
        $this->settings = array_merge($this->settings, $configs);
86
87
        return $this;
88
    }
89
90
    /**
91
     * Set callbackUrl.
92
     *
93
     * @param $url|null
94
     * @return $this
95
     */
96
    public function callbackUrl($url = null)
97
    {
98
        $this->callbackUrl = $url;
99
100
        return $this;
101
    }
102
    
103
    
104
    /**
105
     * Set description.
106
     *
107
     * @param $description
108
     * @return $this
109
     */
110
111
    public function description($description)
112
    {
113
        $this->settings['description'] = $description;
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
     * @param $value|null
149
     * @return $this
150
     */
151
    public function detail($key, $value = null)
152
    {
153
        $this->invoice->detail($key, $value);
154
155
        return $this;
156
    }
157
158
    /**
159
     * Set transaction's id
160
     *
161
     * @param $id
162
     * @return $this
163
     */
164
    public function transactionId($id)
165
    {
166
        $this->invoice->transactionId($id);
167
168
        return $this;
169
    }
170
171
    /**
172
     * Change the driver on the fly.
173
     *
174
     * @param $driver
175
     * @return $this
176
     * @throws \Exception
177
     */
178
    public function via($driver)
179
    {
180
        $this->driver = $driver;
181
        $this->validateDriver();
182
        $this->invoice->via($driver);
183
        $this->settings = $this->config['drivers'][$driver];
184
185
        return $this;
186
    }
187
188
    /**
189
     * Purchase the invoice
190
     *
191
     * @param Invoice $invoice|null
192
     * @param $finalizeCallback|null
193
     * @return $this
194
     * @throws \Exception
195
     */
196
    public function purchase(Invoice $invoice = null, $finalizeCallback = null)
197
    {
198
        if ($invoice) { // create new invoice
199
            $this->invoice($invoice);
200
        }
201
202
        $this->driverInstance = $this->getFreshDriverInstance();
203
204
        //purchase the invoice
205
        $transactionId = $this->driverInstance->purchase();
206
        if ($finalizeCallback) {
207
            call_user_func_array($finalizeCallback, [$this->driverInstance, $transactionId]);
208
        }
209
210
        // dispatch event
211
        event(
212
            new InvoicePurchasedEvent(
213
                $this->driverInstance,
214
                $this->driverInstance->getInvoice()
215
            )
216
        );
217
218
        return $this;
219
    }
220
221
    /**
222
     * Pay the purchased invoice.
223
     *
224
     * @param $initializeCallback|null
225
     * @return mixed
226
     * @throws \Exception
227
     */
228
    public function pay($initializeCallback = null)
229
    {
230
        $this->driverInstance = $this->getDriverInstance();
231
232
        if ($initializeCallback) {
233
            call_user_func($initializeCallback, $this->driverInstance);
234
        }
235
236
        $this->validateInvoice();
237
238
        return $this->driverInstance->pay();
239
    }
240
241
    /**
242
     * Verifies the payment
243
     *
244
     * @param $finalizeCallback|null
245
     *
246
     * @return ReceiptInterface
247
     *
248
     * @throws InvoiceNotFoundException
249
     */
250
    public function verify($finalizeCallback = null) : ReceiptInterface
251
    {
252
        $this->driverInstance = $this->getDriverInstance();
253
        $this->validateInvoice();
254
        $receipt = $this->driverInstance->verify();
255
256
        if (!empty($finalizeCallback)) {
257
            call_user_func($finalizeCallback, $receipt, $this->driverInstance);
258
        }
259
260
        // dispatch event
261
        event(
262
            new InvoiceVerifiedEvent(
263
                $receipt,
264
                $this->driverInstance,
265
                $this->driverInstance->getInvoice()
266
            )
267
        );
268
269
        return $receipt;
270
    }
271
272
    /**
273
     * @param Invoice $invoice
274
     * @return self
275
     */
276
    protected function invoice(Invoice $invoice)
277
    {
278
        $this->invoice = $invoice;
279
280
        return $this;
281
    }
282
283
    /**
284
     * Retrieve current driver instance or generate new one.
285
     *
286
     * @return mixed
287
     * @throws \Exception
288
     */
289
    protected function getDriverInstance()
290
    {
291
        if (!empty($this->driverInstance)) {
292
            return $this->driverInstance;
293
        }
294
295
        return $this->getFreshDriverInstance();
296
    }
297
298
    /**
299
     * Get new driver instance
300
     *
301
     * @return mixed
302
     * @throws \Exception
303
     */
304
    protected function getFreshDriverInstance()
305
    {
306
        $this->validateDriver();
307
        $class = $this->config['map'][$this->driver];
308
309
        if (!empty($this->callbackUrl)) { // use custom callbackUrl if exists
310
            $this->settings['callbackUrl'] = $this->callbackUrl;
311
        }
312
313
        return new $class($this->invoice, $this->settings);
314
    }
315
316
    /**
317
     * Validate Invoice.
318
     *
319
     * @throws InvoiceNotFoundException
320
     */
321
    protected function validateInvoice()
322
    {
323
        if (empty($this->invoice)) {
324
            throw new InvoiceNotFoundException('Invoice not selected or does not exist.');
325
        }
326
    }
327
328
    /**
329
     * Validate driver.
330
     *
331
     * @throws \Exception
332
     */
333
    protected function validateDriver()
334
    {
335
        if (empty($this->driver)) {
336
            throw new DriverNotFoundException('Driver not selected or default driver does not exist.');
337
        }
338
339
        if (empty($this->config['drivers'][$this->driver]) || empty($this->config['map'][$this->driver])) {
340
            throw new DriverNotFoundException('Driver not found in config file. Try updating the package.');
341
        }
342
343
        if (!class_exists($this->config['map'][$this->driver])) {
344
            throw new DriverNotFoundException('Driver source not found. Please update the package.');
345
        }
346
347
        $reflect = new \ReflectionClass($this->config['map'][$this->driver]);
348
349
        if (!$reflect->implementsInterface(DriverInterface::class)) {
350
            throw new \Exception("Driver must be an instance of Contracts\DriverInterface.");
351
        }
352
    }
353
}
354