Completed
Push — master ( d67803...156b7e )
by Iurii
04:44
created

Twocheckout.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * @package 2 Checkout
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\twocheckout;
11
12
use gplcart\core\Config;
13
use gplcart\core\models\Order as OrderModel,
14
    gplcart\core\models\Language as LanguageModel,
15
    gplcart\core\models\Transaction as TransactionModel;
16
use gplcart\modules\omnipay_library\OmnipayLibrary as OmnipayLibraryModule;
17
18
/**
19
 * Main class for 2 Checkout module
20
 */
21
class Twocheckout
22
{
23
24
    /**
25
     * The current order
26
     * @var array
27
     */
28
    protected $data_order;
29
30
    /**
31
     * Omnipay response instance
32
     * @var object
33
     */
34
    protected $response;
35
36
    /**
37
     * Frontend controller instance
38
     * @var \gplcart\core\controllers\frontend\Controller $controller
39
     */
40
    protected $controller;
41
42
    /**
43
     * 2 Checkout Omnipay instance
44
     * @var \Omnipay\TwoCheckoutPlus\Gateway $gateway
45
     */
46
    protected $gateway;
47
48
    /**
49
     * Order model instance
50
     * @var \gplcart\core\models\Order $order
51
     */
52
    protected $order;
53
54
    /**
55
     * Transaction model instance
56
     * @var \gplcart\core\models\Transaction $transaction
57
     */
58
    protected $transaction;
59
60
    /**
61
     * Language model instance
62
     * @var \gplcart\core\models\Language $language
63
     */
64
    protected $language;
65
66
    /**
67
     * Config class instance
68
     * @var \gplcart\core\Config $config
69
     */
70
    protected $config;
71
72
    /**
73
     * Omnipay library module instance
74
     * @var \gplcart\modules\omnipay_library\OmnipayLibrary
75
     */
76
    protected $omnipay_library_module;
77
78
    /**
79
     * Constructor
80
     * @param Config $config
81
     * @param LanguageModel $language
82
     * @param OrderModel $order
83
     * @param TransactionModel $transaction
84
     * @param OmnipayLibraryModule $omnipay_library_module
85
     */
86
    public function __construct(Config $config, LanguageModel $language,
87
            OrderModel $order, TransactionModel $transaction,
88
            OmnipayLibraryModule $omnipay_library_module)
89
    {
90
        $this->order = $order;
91
        $this->config = $config;
92
        $this->language = $language;
93
        $this->transaction = $transaction;
94
95
        $this->omnipay_library_module = $omnipay_library_module;
96
        $this->gateway = $this->omnipay_library_module->getGatewayInstance('TwoCheckoutPlus');
97
    }
98
99
    /**
100
     * Module info
101
     * @return array
102
     */
103
    public function info()
104
    {
105
        return array(
106
            'core' => '1.x',
107
            'name' => '2 Checkout',
108
            'version' => '1.0.0-alfa.1',
109
            'description' => 'Provides 2 Checkout payment method',
110
            'author' => 'Iurii Makukh <[email protected]>',
111
            'license' => 'GNU General Public License 3.0',
112
            'dependencies' => array('omnipay_library' => '>= 1.0'),
113
            'configure' => 'admin/module/settings/twocheckout',
114
            'settings' => $this->getDefaultSettings()
115
        );
116
    }
117
118
    /**
119
     * Returns an array of default module settings
120
     * @return array
121
     */
122
    protected function getDefaultSettings()
123
    {
124
        return array(
125
            'test' => true,
126
            'status' => true,
127
            'order_status_success' => $this->order->getStatusProcessing(),
128
            // Gateway specific params
129
            'accountNumber' => '',
130
            'secretWord' => ''
131
        );
132
    }
133
134
    /**
135
     * Implements hook "route.list"
136
     * @param array $routes 
137
     */
138
    public function hookRouteList(array &$routes)
139
    {
140
        $routes['admin/module/settings/twocheckout'] = array(
141
            'access' => 'module_edit',
142
            'handlers' => array(
143
                'controller' => array('gplcart\\modules\\twocheckout\\controllers\\Settings', 'editSettings')
144
            )
145
        );
146
    }
147
148
    /**
149
     * Implements hook "module.enable.before"
150
     * @param mixed $result
151
     */
152
    public function hookModuleEnableBefore(&$result)
153
    {
154
        $this->validateGateway($result);
155
    }
156
157
    /**
158
     * Implements hook "module.install.before"
159
     * @param mixed $result
160
     */
161
    public function hookModuleInstallBefore(&$result)
162
    {
163
        $this->validateGateway($result);
164
    }
165
166
    /**
167
     * Checks the gateway object is loaded
168
     * @param mixed $result
169
     */
170
    protected function validateGateway(&$result)
171
    {
172
        if (!$this->gateway instanceof \Omnipay\TwoCheckoutPlus\Gateway) {
0 ignored issues
show
The class Omnipay\TwoCheckoutPlus\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...
173
            $result = $this->language->text('Unable to load @name gateway', array('@name' => '2 Checkout'));
174
        }
175
    }
176
177
    /**
178
     * Implements hook "payment.methods"
179
     * @param array $methods 
180
     */
181
    public function hookPaymentMethods(array &$methods)
182
    {
183
        $methods['twocheckout'] = array(
184
            'module' => 'twocheckout',
185
            'image' => 'image/icon.png',
186
            'status' => $this->getStatus(),
187
            'title' => $this->language->text('2 Checkout'),
188
            'template' => array('complete' => 'pay')
189
        );
190
    }
191
192
    /**
193
     * Returns a module setting
194
     * @param string $name
195
     * @param mixed $default
196
     * @return mixed
197
     */
198
    protected function setting($name, $default = null)
199
    {
200
        return $this->config->module('twocheckout', $name, $default);
201
    }
202
203
    /**
204
     * Returns the current status of the payment method
205
     */
206
    protected function getStatus()
207
    {
208
        return $this->setting('status') && $this->setting('accountNumber') && $this->setting('secretWord');
209
    }
210
211
    /**
212
     * Implements hook "order.add.before"
213
     * @param array $order
214
     */
215
    public function hookOrderAddBefore(array &$order)
216
    {
217
        // Adjust order status before creation
218
        // We want to get payment in advance, so assign "awaiting payment" status
219
        if ($order['payment'] === 'twocheckout') {
220
            $order['status'] = $this->order->getStatusAwaitingPayment();
221
        }
222
    }
223
224
    /**
225
     * Implements hook "order.checkout.complete"
226
     * @param string $message
227
     * @param array $order
228
     */
229
    public function hookOrderCompleteMessage(&$message, $order)
230
    {
231
        if ($order['payment'] === 'twocheckout') {
232
            $message = ''; // Hide default message
233
        }
234
    }
235
236
    /**
237
     * Implements hook "order.complete.page"
238
     * @param array $order
239
     * @param \gplcart\core\controllers\frontend\Controller $controller
240
     * @return null
241
     */
242
    public function hookOrderCompletePage(array $order, $controller)
243
    {
244
        $this->data_order = $order;
245
        $this->controller = $controller;
246
247
        if ($order['payment'] === 'twocheckout') {
248
            $this->submit();
249
            $this->complete();
250
        }
251
    }
252
253
    /**
254
     * Performs actions when purchase is completed
255
     */
256
    protected function complete()
257
    {
258
        if ($this->controller->isQuery('paid')) {
259
            $this->response = $this->gateway->completePurchase($this->getPurchaseParams())->send();
260
            $this->processResponse();
261
        }
262
    }
263
264
    /**
265
     * Handles submitted payment
266
     */
267
    protected function submit()
268
    {
269
        if ($this->controller->isPosted('pay')) {
270
271
            $this->gateway->setDemoMode((bool) $this->setting('test'));
272
            $this->gateway->setCurrency($this->data_order['currency']);
273
            $this->gateway->setSecretWord($this->setting('secretWord'));
274
            $this->gateway->setAccountNumber($this->setting('accountNumber'));
275
276
            $this->gateway->setCart(array(array(
277
                    'quantity' => 1,
278
                    'type' => 'product',
279
                    'price' => $this->data_order['total_formatted_number'],
280
                    'name' => $this->language->text('Order #@num', array('@num' => $this->data_order['order_id']))
281
            )));
282
283
            $this->response = $this->gateway->purchase($this->getPurchaseParams())->send();
284
285
            if ($this->response->isRedirect()) {
286
                $this->response->redirect();
287
            } else if (!$this->response->isSuccessful()) {
288
                $this->redirectError();
289
            }
290
        }
291
    }
292
293
    /**
294
     * Returns an array of purchase parameters
295
     * @return array
296
     */
297
    protected function getPurchaseParams()
298
    {
299
        return array(
300
            'currency' => $this->data_order['currency'],
301
            'total' => $this->data_order['total_formatted_number'],
302
            'cancelUrl' => $this->controller->url("checkout/complete/{$this->data_order['order_id']}", array('cancel' => true), true),
303
            'returnUrl' => $this->controller->url("checkout/complete/{$this->data_order['order_id']}", array('paid' => true), true)
304
        );
305
    }
306
307
    /**
308
     * Processes gateway response
309
     */
310
    protected function processResponse()
311
    {
312
        if ($this->response->isSuccessful()) {
313
            $this->updateOrderStatus();
314
            $this->addTransaction();
315
            $this->redirectSuccess();
316
        } else if ($this->response->isRedirect()) {
317
            $this->response->redirect();
318
        } else {
319
            $this->redirectError();
320
        }
321
    }
322
323
    /**
324
     * Redirect on error transaction
325
     */
326
    protected function redirectError()
327
    {
328
        $this->controller->redirect('', $this->response->getMessage(), 'warning', true);
329
    }
330
331
    /**
332
     * Redirect on successful transaction
333
     */
334
    protected function redirectSuccess()
335
    {
336
        $vars = array(
337
            '@num' => $this->data_order['order_id'],
338
            '@status' => $this->order->getStatusName($this->data_order['status'])
339
        );
340
341
        $message = $this->controller->text('Thank you! Payment has been made. Order #@num, status: @status', $vars);
342
        $this->controller->redirect('/', $message, 'success', true);
343
    }
344
345
    /**
346
     * Update order status after successful transaction
347
     */
348
    protected function updateOrderStatus()
349
    {
350
        $data = array(
351
            'status' => $this->setting('order_status_success'));
352
        $this->order->update($this->data_order['order_id'], $data);
353
354
        // Load fresh data
355
        $this->data_order = $this->order->get($this->data_order['order_id']);
356
    }
357
358
    /**
359
     * Adds a transaction
360
     * @return integer
361
     */
362
    protected function addTransaction()
363
    {
364
        $transaction = array(
365
            'total' => $this->data_order['total'],
366
            'order_id' => $this->data_order['order_id'],
367
            'currency' => $this->data_order['currency'],
368
            'payment_method' => $this->data_order['payment'],
369
            'gateway_transaction_id' => $this->response->getTransactionReference()
370
        );
371
372
        return $this->transaction->add($transaction);
373
    }
374
375
}
376