Completed
Push — master ( 48f758...9f215e )
by Iurii
01:18
created

Twocheckout::redirectError()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
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\Module;
13
14
/**
15
 * Main class for 2 Checkout module
16
 */
17
class Twocheckout extends Module
18
{
19
20
    /**
21
     * The current order
22
     * @var array
23
     */
24
    protected $data_order;
25
26
    /**
27
     * Omnipay response instance
28
     * @var object
29
     */
30
    protected $response;
31
32
    /**
33
     * Frontend controller instance
34
     * @var \gplcart\core\controllers\frontend\Controller $controller
35
     */
36
    protected $controller;
37
38
    /**
39
     * Language model instance
40
     * @var \gplcart\core\models\Language $language
41
     */
42
    protected $language;
43
44
    /**
45
     * Order model instance
46
     * @var \gplcart\core\models\Order $order
47
     */
48
    protected $order;
49
50
    /**
51
     * @param LanguageModel $language
52
     */
53
    public function __construct(LanguageModel $language)
54
    {
55
        parent::__construct();
56
57
        $this->language = $language;
0 ignored issues
show
Documentation Bug introduced by
It seems like $language of type object<gplcart\modules\twocheckout\LanguageModel> is incompatible with the declared type object<gplcart\core\models\Language> of property $language.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
58
    }
59
60
    /**
61
     * Implements hook "route.list"
62
     * @param array $routes
63
     */
64
    public function hookRouteList(array &$routes)
65
    {
66
        $routes['admin/module/settings/twocheckout'] = array(
67
            'access' => 'module_edit',
68
            'handlers' => array(
69
                'controller' => array('gplcart\\modules\\twocheckout\\controllers\\Settings', 'editSettings')
70
            )
71
        );
72
    }
73
74
    /**
75
     * Implements hook "module.enable.before"
76
     * @param mixed $result
77
     */
78
    public function hookModuleEnableBefore(&$result)
79
    {
80
        try {
81
            $this->getGatewayInstance();
82
        } catch (\InvalidArgumentException $ex) {
83
            $result = $ex->getMessage();
84
        }
85
    }
86
87
    /**
88
     * Implements hook "module.install.before"
89
     * @param mixed $result
90
     */
91
    public function hookModuleInstallBefore(&$result)
92
    {
93
        try {
94
            $this->getGatewayInstance();
95
        } catch (\InvalidArgumentException $ex) {
96
            $result = $ex->getMessage();
97
        }
98
    }
99
100
    /**
101
     * Get gateway instance
102
     * @return object
103
     * @throws \InvalidArgumentException
104
     */
105
    protected function getGatewayInstance()
106
    {
107
        /* @var $model \gplcart\modules\omnipay_library\OmnipayLibrary */
108
        $model = $this->getInstance('omnipay_library');
109
110
        $instance = $model->getGatewayInstance('TwoCheckoutPlus');
111
112
        if (!$instance instanceof \Omnipay\TwoCheckoutPlus\Gateway) {
0 ignored issues
show
Bug introduced by
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...
113
            throw new \InvalidArgumentException('Object is not instance of Omnipay\TwoCheckoutPlus\Gateway');
114
        }
115
116
        return $instance;
117
    }
118
119
    /**
120
     * Implements hook "payment.methods"
121
     * @param array $methods
122
     */
123
    public function hookPaymentMethods(array &$methods)
124
    {
125
        $methods['twocheckout'] = array(
126
            'module' => 'twocheckout',
127
            'image' => 'image/icon.png',
128
            'status' => $this->getStatus(),
129
            'title' => $this->language->text('2 Checkout'),
130
            'template' => array('complete' => 'pay')
131
        );
132
    }
133
134
    /**
135
     * Returns a module setting
136
     * @param string $name
137
     * @param mixed $default
138
     * @return mixed
139
     */
140
    protected function setting($name, $default = null)
141
    {
142
        return $this->config->module('twocheckout', $name, $default);
143
    }
144
145
    /**
146
     * Returns the current status of the payment method
147
     */
148
    protected function getStatus()
149
    {
150
        return $this->setting('status') && $this->setting('accountNumber') && $this->setting('secretWord');
151
    }
152
153
    /**
154
     * Implements hook "order.add.before"
155
     * @param array $order
156
     * @param \gplcart\core\models\Order $object
157
     */
158
    public function hookOrderAddBefore(array &$order, $object)
159
    {
160
        // Adjust order status before creation
161
        // We want to get payment in advance, so assign "awaiting payment" status
162
        if ($order['payment'] === 'twocheckout') {
163
            $order['status'] = $object->getStatusAwaitingPayment();
164
        }
165
    }
166
167
    /**
168
     * Implements hook "order.checkout.complete"
169
     * @param string $message
170
     * @param array $order
171
     */
172
    public function hookOrderCompleteMessage(&$message, $order)
173
    {
174
        if ($order['payment'] === 'twocheckout') {
175
            $message = ''; // Hide default message
176
        }
177
    }
178
179
    /**
180
     * Implements hook "order.complete.page"
181
     * @param array $order
182
     * @param \gplcart\core\models\Order $model
183
     * @param \gplcart\core\controllers\frontend\Controller $controller
184
     */
185
    public function hookOrderCompletePage(array $order, $model, $controller)
186
    {
187
        $this->order = $model;
188
        $this->data_order = $order;
189
        $this->controller = $controller;
190
191
        if ($order['payment'] === 'twocheckout') {
192
            $this->submit();
193
            $this->complete();
194
        }
195
    }
196
197
    /**
198
     * Performs actions when purchase is completed
199
     */
200
    protected function complete()
201
    {
202
        if ($this->controller->isQuery('paid')) {
203
            $gateway = $this->getGatewayInstance();
204
            $this->response = $gateway->completePurchase($this->getPurchaseParams())->send();
205
            $this->processResponse();
206
        }
207
    }
208
209
    /**
210
     * Handles submitted payment
211
     */
212
    protected function submit()
213
    {
214
        if ($this->controller->isPosted('pay')) {
215
216
            $gateway = $this->getGatewayInstance();
217
            $gateway->setDemoMode((bool) $this->setting('test'));
218
            $gateway->setCurrency($this->data_order['currency']);
219
            $gateway->setSecretWord($this->setting('secretWord'));
220
            $gateway->setAccountNumber($this->setting('accountNumber'));
221
222
            $gateway->setCart(array(array(
223
                    'quantity' => 1,
224
                    'type' => 'product',
225
                    'price' => $this->data_order['total_formatted_number'],
226
                    'name' => $this->language->text('Order #@num', array('@num' => $this->data_order['order_id']))
227
            )));
228
229
            $this->response = $gateway->purchase($this->getPurchaseParams())->send();
230
231
            if ($this->response->isRedirect()) {
232
                $this->response->redirect();
233
            } else if (!$this->response->isSuccessful()) {
234
                $this->redirectError();
235
            }
236
        }
237
    }
238
239
    /**
240
     * Returns an array of purchase parameters
241
     * @return array
242
     */
243
    protected function getPurchaseParams()
244
    {
245
        return array(
246
            'currency' => $this->data_order['currency'],
247
            'total' => $this->data_order['total_formatted_number'],
248
            'cancelUrl' => $this->controller->url("checkout/complete/{$this->data_order['order_id']}", array('cancel' => true), true),
249
            'returnUrl' => $this->controller->url("checkout/complete/{$this->data_order['order_id']}", array('paid' => true), true)
250
        );
251
    }
252
253
    /**
254
     * Processes gateway response
255
     */
256
    protected function processResponse()
257
    {
258
        if ($this->response->isSuccessful()) {
259
            $this->updateOrderStatus();
260
            $this->addTransaction();
261
            $this->redirectSuccess();
262
        } else if ($this->response->isRedirect()) {
263
            $this->response->redirect();
264
        } else {
265
            $this->redirectError();
266
        }
267
    }
268
269
    /**
270
     * Redirect on error transaction
271
     */
272
    protected function redirectError()
273
    {
274
        $this->controller->redirect('', $this->response->getMessage(), 'warning', true);
275
    }
276
277
    /**
278
     * Redirect on successful transaction
279
     */
280
    protected function redirectSuccess()
281
    {
282
        $vars = array(
283
            '@num' => $this->data_order['order_id'],
284
            '@status' => $this->order->getStatusName($this->data_order['status'])
285
        );
286
287
        $message = $this->language->text('Thank you! Payment has been made. Order #@num, status: @status', $vars);
288
        $this->controller->redirect('/', $message, 'success', true);
289
    }
290
291
    /**
292
     * Update order status after successful transaction
293
     */
294
    protected function updateOrderStatus()
295
    {
296
        $data = array('status' => $this->setting('order_status_success'));
297
        $this->order->update($this->data_order['order_id'], $data);
298
        $this->data_order = $this->order->get($this->data_order['order_id']);
299
    }
300
301
    /**
302
     * Adds a transaction
303
     * @return integer
304
     */
305
    protected function addTransaction()
306
    {
307
        $transaction = array(
308
            'total' => $this->data_order['total'],
309
            'order_id' => $this->data_order['order_id'],
310
            'currency' => $this->data_order['currency'],
311
            'payment_method' => $this->data_order['payment'],
312
            'gateway_transaction_id' => $this->response->getTransactionReference()
313
        );
314
315
        /* @var $object \gplcart\core\models\Transaction */
316
        $object = $this->getModel('Transaction');
317
        return $object->add($transaction);
318
    }
319
320
}
321