Completed
Push — master ( beb870...36b3a3 )
by mahdi
02:58
created

PaymentManager::validateInvoice()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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