Completed
Push — master ( 8ac3d8...0edb69 )
by Iurii
02:08
created

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