Completed
Push — master ( d09259...594c85 )
by mahdi
02:18
created

PaymentManager::pay()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 9
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\Exceptions\DriverNotFoundException;
7
use Shetabit\Payment\Exceptions\InvoiceNotFoundException;
8
9
class PaymentManager
10
{
11
    /**
12
     * Payment Configuration.
13
     *
14
     * @var array
15
     */
16
    protected $config;
17
18
    /**
19
     * Payment Driver Settings.
20
     *
21
     * @var array
22
     */
23
    protected $settings;
24
25
    /**
26
     * Payment Driver Name.
27
     *
28
     * @var string
29
     */
30
    protected $driver;
31
32
    /**
33
     * Payment Driver Instance.
34
     *
35
     * @var object
36
     */
37
    protected $driverInstance;
38
39
    /**
40
     * @var InvoiceBuilder
41
     */
42
    protected $invoice;
43
44
    /**
45
     * PaymentManager constructor.
46
     *
47
     * @param $config
48
     * @throws \Exception
49
     */
50
    public function __construct($config)
51
    {
52
        $this->config = $config;
53
        $this->setInvoice(new InvoiceBuilder());
54
        $this->via($this->config['default']);
55
    }
56
57
    /**
58
     * Set payment amount.
59
     *
60
     * @param $amount
61
     * @return $this
62
     * @throws \Exception
63
     */
64
    public function amount($amount)
65
    {
66
        $this->invoice->amount($amount);
67
68
        return $this;
69
    }
70
71
    /**
72
     * Set a piece of data to the details.
73
     *
74
     * @param $key
75
     * @param null $value
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $value is correct as it would always require null to be passed?
Loading history...
76
     * @return $this
77
     */
78
    public function detail($key, $value = null)
79
    {
80
        $this->invoice->detail($key, $value);
81
82
        return $this;
83
    }
84
85
    /**
86
     * Set transaction's id
87
     *
88
     * @param $id
89
     * @return $this
90
     */
91
    public function transactionId($id) {
92
        $this->invoice->transactionId($id);
93
94
        return $this;
95
    }
96
97
    /**
98
     * Change the driver on the fly.
99
     *
100
     * @param $driver
101
     * @return $this
102
     * @throws \Exception
103
     */
104
    public function via($driver)
105
    {
106
        $this->driver = $driver;
107
        $this->validateDriver();
108
        $this->invoice->via($driver);
109
        $this->settings = $this->config['drivers'][$driver];
110
111
        return $this;
112
    }
113
114
    /**
115
     * Purchase the invoice
116
     *
117
     * @param InvoiceBuilder $invoice
118
     * @param null $initializeCallback
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $initializeCallback is correct as it would always require null to be passed?
Loading history...
119
     * @param null $finalizeCallback
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $finalizeCallback is correct as it would always require null to be passed?
Loading history...
120
     * @return $this
121
     * @throws \Exception
122
     */
123
    public function purchase(InvoiceBuilder $invoice, $initializeCallback = null, $finalizeCallback = null)
124
    {
125
        $this->setInvoice($invoice);
126
        $this->driverInstance = $this->getFreshDriverInstance();
127
        if(!empty($initializeCallback)) {
128
            call_user_func($initializeCallback, $this->driverInstance);
129
        }
130
131
        //purchase the invoice
132
        $body = $this->driverInstance->purchase();
133
        if($finalizeCallback) {
0 ignored issues
show
introduced by
$finalizeCallback is of type null, thus it always evaluated to false.
Loading history...
134
            call_user_func_array($finalizeCallback, [$this->driverInstance, $body]);
135
        }
136
137
        return $this;
138
    }
139
140
    /**
141
     * Pay the purchased invoice.
142
     *
143
     * @param null $initializeCallback
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $initializeCallback is correct as it would always require null to be passed?
Loading history...
144
     * @return mixed
145
     * @throws \Exception
146
     */
147
    public function pay($initializeCallback = null)
148
    {
149
        $this->driverInstance = $this->getDriverInstance();
150
        if($initializeCallback) {
0 ignored issues
show
introduced by
$initializeCallback is of type null, thus it always evaluated to false.
Loading history...
151
            call_user_func($initializeCallback, $this->driverInstance);
152
        }
153
        $this->validateInvoice();
154
155
        return $this->driverInstance->pay();
156
    }
157
158
    /**
159
     * Verifies the payment
160
     *
161
     * @param $initializeCallback
162
     * @return mixed
163
     * @throws \Exception
164
     */
165
    public function verify($initializeCallback = null)
166
    {
167
        $this->driverInstance = $this->getDriverInstance();
168
        if(!empty($initializeCallback)) {
169
            call_user_func($initializeCallback, $this->driverInstance);
170
        }
171
        $this->validateInvoice();
172
173
        return $this->driverInstance->verify();
174
    }
175
176
    /**
177
     * @param InvoiceBuilder $invoice
178
     * @return self
179
     */
180
    protected function setInvoice(InvoiceBuilder $invoice)
181
    {
182
        $this->invoice = $invoice;
183
184
        return $this;
185
    }
186
187
    /**
188
     * Retrieve current driver instance or generate new one.
189
     *
190
     * @return mixed
191
     * @throws \Exception
192
     */
193
    protected function getDriverInstance()
194
    {
195
        if(!empty($this->driverInstance)) {
196
            return $this->driverInstance;
197
        }
198
199
        return $this->getFreshDriverInstance();
200
    }
201
202
    /**
203
     * Get new driver instance
204
     *
205
     * @return mixed
206
     * @throws \Exception
207
     */
208
    protected function getFreshDriverInstance() {
209
        $this->validateDriver();
210
        $class = $this->config['map'][$this->driver];
211
212
        return new $class($this->invoice,$this->settings);
213
    }
214
215
    /**
216
     * Validate Invoice.
217
     *
218
     * @throws InvoiceNotFoundException
219
     */
220
    protected function validateInvoice() {
221
        if(empty($this->invoice)) {
222
            throw new InvoiceNotFoundException('Invoice not selected or does not exist.');
223
        }
224
    }
225
226
    /**
227
     * Validate driver.
228
     *
229
     * @throws \Exception
230
     */
231
    protected function validateDriver()
232
    {
233
        if (empty($this->driver)) {
234
            throw new DriverNotFoundException('Driver not selected or default driver does not exist.');
235
        }
236
237
        if (empty($this->config['drivers'][$this->driver]) || empty($this->config['map'][$this->driver])) {
238
            throw new DriverNotFoundException('Driver not found in config file. Try updating the package.');
239
        }
240
241
        if (! class_exists($this->config['map'][$this->driver])) {
242
            throw new DriverNotFoundException('Driver source not found. Please update the package.');
243
        }
244
245
        $reflect = new \ReflectionClass($this->config['map'][$this->driver]);
246
247
        if (! $reflect->implementsInterface(Contracts\DriverInterface::class)) {
248
            throw new \Exception("Driver must be an instance of Contracts\DriverInterface.");
249
        }
250
    }
251
}
252