Main::hookPaymentMethods()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 1
1
<?php
2
3
/**
4
 * @package Stripe
5
 * @author Iurii Makukh <[email protected]>
6
 * @copyright Copyright (c) 2017, Iurii Makukh <[email protected]>
7
 * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License 3.0
8
 */
9
10
namespace gplcart\modules\stripe;
11
12
use Exception;
13
use gplcart\core\Module;
14
use Omnipay\Stripe\Gateway;
15
use UnexpectedValueException;
16
17
/**
18
 * Main class for Stripe module
19
 */
20
class Main
21
{
22
23
    /**
24
     * The current order
25
     * @var array
26
     */
27
    protected $data_order;
28
29
    /**
30
     * Stripe token
31
     * @var string
32
     */
33
    protected $data_token;
34
35
    /**
36
     * Omnipay response instance
37
     * @var object
38
     */
39
    protected $response;
40
41
    /**
42
     * Frontend controller instance
43
     * @var \gplcart\core\controllers\frontend\Controller $controller
44
     */
45
    protected $controller;
46
47
    /**
48
     * Order model instance
49
     * @var \gplcart\core\models\Order $order
50
     */
51
    protected $order;
52
53
    /**
54
     * Module class instance
55
     * @var \gplcart\core\Module $module
56
     */
57
    protected $module;
58
59
    /**
60
     * @param Module $module
61
     */
62
    public function __construct(Module $module)
63
    {
64
        $this->module = $module;
65
    }
66
67
    /**
68
     * Implements hook "module.enable.before"
69
     * @param mixed $result
70
     */
71
    public function hookModuleEnableBefore(&$result)
72
    {
73
        $this->checkGateway($result);
74
    }
75
76
    /**
77
     * Implements hook "module.install.before"
78
     * @param mixed $result
79
     */
80
    public function hookModuleInstallBefore(&$result)
81
    {
82
        $this->checkGateway($result);
83
    }
84
85
    /**
86
     * Implements hook "route.list"
87
     * @param array $routes
88
     */
89
    public function hookRouteList(array &$routes)
90
    {
91
        $routes['admin/module/settings/stripe'] = array(
92
            'access' => 'module_edit',
93
            'handlers' => array(
94
                'controller' => array('gplcart\\modules\\stripe\\controllers\\Settings', 'editSettings')
95
            )
96
        );
97
    }
98
99
    /**
100
     * Implements hook "payment.methods"
101
     * @param array $methods
102
     */
103
    public function hookPaymentMethods(array &$methods)
104
    {
105
        $methods['stripe'] = array(
106
            'module' => 'stripe',
107
            'image' => 'image/icon.png',
108
            'status' => $this->getStatus(),
109
            'title' => 'Stripe',
110
            'template' => array('complete' => 'pay')
111
        );
112
    }
113
114
    /**
115
     * Implements hook "order.add.before"
116
     * @param array $order
117
     * @param \gplcart\core\models\Order $model
118
     */
119
    public function hookOrderAddBefore(array &$order, $model)
120
    {
121
        // Adjust order status before creation
122
        // We want to get payment in advance, so assign "awaiting payment" status
123
        if ($order['payment'] === 'stripe') {
124
            $order['status'] = $model->getStatusAwaitingPayment();
125
        }
126
    }
127
128
    /**
129
     * Implements hook "order.checkout.complete"
130
     * @param string $message
131
     * @param array $order
132
     */
133
    public function hookOrderCompleteMessage(&$message, $order)
134
    {
135
        if ($order['payment'] === 'stripe') {
136
            $message = ''; // Hide default message
137
        }
138
    }
139
140
    /**
141
     * Implements hook "order.complete.page"
142
     * @param array $order
143
     * @param \gplcart\core\models\Order $model
144
     * @param \gplcart\core\controllers\frontend\Controller $controller
145
     */
146
    public function hookOrderCompletePage(array $order, $model, $controller)
147
    {
148
        $this->setCompletePage($order, $model, $controller);
149
    }
150
151
    /**
152
     * Check that Stripe gateway object is loaded
153
     * @param mixed $result
154
     */
155
    protected function checkGateway(&$result)
156
    {
157
        try {
158
            $this->getGateway();
159
        } catch (Exception $ex) {
160
            $result = $ex->getMessage();
161
        }
162
    }
163
164
    /**
165
     * Set up order complete page
166
     * @param array $order
167
     * @param \gplcart\core\models\Order $model
168
     * @param \gplcart\core\controllers\frontend\Controller $controller
169
     */
170
    protected function setCompletePage(array $order, $model, $controller)
171
    {
172
        if ($order['payment'] === 'stripe') {
173
174
            $this->order = $model;
175
            $this->data_order = $order;
176
            $this->controller = $controller;
177
178
            $this->submitPayment();
179
180
            $controller->setJs('https://js.stripe.com/v2');
181
            $controller->setJs('system/modules/stripe/js/common.js');
182
            $controller->setJsSettings('stripe', array('key' => $this->getPublicKey()));
183
        }
184
    }
185
186
    /**
187
     * Returns Stripe gateway object
188
     * @return \Omnipay\Stripe\Gateway
189
     * @throws UnexpectedValueException
190
     */
191
    public function getGateway()
192
    {
193
        /* @var $module \gplcart\modules\omnipay_library\Main */
194
        $module = $this->module->getInstance('omnipay_library');
195
196
        /** @var \Omnipay\Stripe\Gateway $gateway */
197
        $gateway = $module->getGatewayInstance('Stripe');
198
199
        if (!$gateway instanceof Gateway) {
0 ignored issues
show
Bug introduced by
The class Omnipay\Stripe\Gateway does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
200
            throw new UnexpectedValueException('Gateway must be instance of Omnipay\Stripe\Gateway');
201
        }
202
203
        return $gateway;
204
    }
205
206
    /**
207
     * Returns a public API key
208
     * @return string
209
     */
210
    public function getPublicKey()
211
    {
212
        $key = $this->getModuleSetting('test') ? 'test_public_key' : 'live_public_key';
213
        return $this->getModuleSetting($key);
214
    }
215
216
    /**
217
     * Returns a secret API key
218
     * @return string
219
     */
220
    public function getSecretKey()
221
    {
222
        $key = $this->getModuleSetting('test') ? 'test_key' : 'live_key';
223
        return $this->getModuleSetting($key);
224
    }
225
226
    /**
227
     * Returns a module setting
228
     * @param string $name
229
     * @param mixed $default
230
     * @return mixed
231
     */
232
    protected function getModuleSetting($name, $default = null)
233
    {
234
        return $this->module->getSettings('stripe', $name, $default);
235
    }
236
237
    /**
238
     * Returns the current status of the payment method
239
     */
240
    protected function getStatus()
241
    {
242
        if (!$this->getModuleSetting('status')) {
243
            return false;
244
        }
245
246
        if ($this->getModuleSetting('test')) {
247
            return $this->getModuleSetting('test_key') && $this->getModuleSetting('test_public_key');
248
        }
249
250
        return $this->getModuleSetting('live_key') && $this->getModuleSetting('live_public_key');
251
    }
252
253
    /**
254
     * Handles submitted payment
255
     */
256
    protected function submitPayment()
257
    {
258
        $this->data_token = $this->controller->getPosted('stripeToken', '', true, 'string');
259
260
        if (!empty($this->data_token)) {
261
262
            $params = array(
263
                'token' => $this->data_token,
264
                'currency' => $this->data_order['currency'],
265
                'amount' => $this->data_order['total_formatted_number']
266
            );
267
268
            $gateway = $this->getGateway();
269
            $gateway->setApiKey($this->getSecretKey());
270
            $this->response = $gateway->purchase($params)->send();
271
            $this->processResponse();
272
        }
273
    }
274
275
    /**
276
     * Processes gateway response
277
     */
278
    protected function processResponse()
279
    {
280
        if ($this->response->isSuccessful()) {
281
            $this->updateOrderStatus();
282
            $this->addTransaction();
283
            $this->redirectSuccess();
284
        } else if ($this->response->isRedirect()) {
285
            $this->response->redirect();
286
        } else {
287
            $this->controller->redirect('', $this->response->getMessage(), 'warning', true);
288
        }
289
    }
290
291
    /**
292
     * Redirect on successful transaction
293
     */
294
    protected function redirectSuccess()
295
    {
296
        $vars = array(
297
            '@num' => $this->data_order['order_id'],
298
            '@status' => $this->order->getStatusName($this->data_order['status'])
299
        );
300
301
        $message = $this->controller->text('Thank you! Payment has been made. Order #@num, status: @status', $vars);
302
        $this->controller->redirect('/', $message, 'success', true);
303
    }
304
305
    /**
306
     * Update order status after successful transaction
307
     */
308
    protected function updateOrderStatus()
309
    {
310
        $data = array('status' => $this->getModuleSetting('order_status_success'));
311
        $this->order->update($this->data_order['order_id'], $data);
312
        $this->data_order = $this->order->get($this->data_order['order_id']);
313
    }
314
315
    /**
316
     * Adds a transaction
317
     * @return integer
318
     */
319
    protected function addTransaction()
320
    {
321
        /* @var $model \gplcart\core\models\Transaction */
322
        $model = gplcart_instance_model('Transaction');
323
324
        $transaction = array(
325
            'total' => $this->data_order['total'],
326
            'order_id' => $this->data_order['order_id'],
327
            'currency' => $this->data_order['currency'],
328
            'payment_method' => $this->data_order['payment'],
329
            'gateway_transaction_id' => $this->response->getTransactionReference()
330
        );
331
332
        return $model->add($transaction);
333
    }
334
335
}
336