Completed
Push — master ( 9f215e...61f970 )
by Iurii
01:09
created

Twocheckout.php (1 issue)

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\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) {
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