plgVmOnPaymentResponseReceived()   C
last analyzed

Complexity

Conditions 8
Paths 40

Size

Total Lines 45
Code Lines 21

Duplication

Lines 4
Ratio 8.89 %

Importance

Changes 5
Bugs 1 Features 1
Metric Value
cc 8
eloc 21
c 5
b 1
f 1
nc 40
nop 1
dl 4
loc 45
rs 5.3846
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 26 and the first side effect is on line 31.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * The MIT License (MIT)
4
 *
5
 * Copyright (c) 2011-2014 BitPay
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25
26
function bplog($contents)
27
{
28
    error_log($contents);
29
}
30
31
defined('_JEXEC') or die('Restricted access');
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
32
33
if (!class_exists('vmPSPlugin'))
34
{
35
    require(JPATH_VM_PLUGINS . DS . 'vmpsplugin.php');
36
}
37
38
class plgVmPaymentBitPay extends vmPSPlugin
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
39
{
40
41
    /**
42
     * @param $subject
43
     * @param $config
44
     */
45
    function __construct(&$subject, $config)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
46
    {
47
        parent::__construct($subject, $config);
48
        $this->_loggable   = true;
49
        $this->tableFields = array_keys($this->getTableSQLFields());
50
        $this->_tablepkey = 'id';
51
        $this->_tableId = 'id';
52
        $varsToPush        = $this->getVarsToPush();
53
        $this->setConfigParameterable($this->_configTableFieldName, $varsToPush);
54
    }
55
56
    /**
57
     * Create the table for this plugin if it does not yet exist.
58
     *
59
     * @return
60
     */
61
    public function getVmPluginCreateTableSQL()
62
    {
63
        return $this->createTableSQL('Payment BitPay Table');
64
    }
65
66
    /**
67
     * Fields to create the payment table
68
     *
69
     * @return array
70
     */
71
    function getTableSQLFields()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
72
    {
73
        $SQLfields = array(
74
            'id'                          => 'int(1) UNSIGNED NOT NULL AUTO_INCREMENT',
75
            'virtuemart_order_id'         => 'int(1) UNSIGNED',
76
            'order_number'                => 'char(64)',
77
            'virtuemart_paymentmethod_id' => 'mediumint(1) UNSIGNED',
78
            'payment_name'                => 'varchar(5000)',
79
            'payment_order_total'         => 'decimal(15,5) NOT NULL DEFAULT \'0.00000\'',
80
            'payment_currency'            => 'char(3)',
81
            'logo'			  => 'varchar(5000)'
82
        );
83
84
        return $SQLfields;
85
    }
86
87
88
    /**
89
     * Display stored payment data for an order
90
     *
91
     * @param $virtuemart_order_id
92
     * @param $virtuemart_payment_id
93
     *
94
     * @return
95
     */
96
    function plgVmOnShowOrderBEPayment($virtuemart_order_id, $virtuemart_payment_id)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
97
    {
98
        if (!$this->selectedThisByMethodId($virtuemart_payment_id))
99
        {
100
            return NULL; // Another method was selected, do nothing
101
        }
102
103
        if (!($paymentTable = $this->getDataByOrderId($virtuemart_order_id)))
104
        {
105
            return NULL;
106
        }
107
        VmConfig::loadJLang('com_virtuemart');
108
109
        $html = '<table class="adminlist">' . "\n";
110
        $html .= $this->getHtmlHeaderBE();
111
        $html .= $this->getHtmlRowBE('BITPAY_PAYMENT_NAME', $paymentTable->payment_name);
112
        $html .= $this->getHtmlRowBE('BITPAY_PAYMENT_TOTAL_CURRENCY', $paymentTable->payment_order_total . ' ' . $paymentTable->payment_currency);
113
        $html .= '</table>' . "\n";
114
115
        return $html;
116
    }
117
118
    /**
119
     * @param VirtueMartCart $cart
120
     * @param                $method
121
     * @param array          $cart_prices
122
     *
123
     * @return
124
     */
125
    function getCosts(VirtueMartCart $cart, $method, $cart_prices)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
126
    {
127
        if (preg_match('/%$/', $method->cost_percent_total))
128
        {
129
            $cost_percent_total = substr($method->cost_percent_total, 0, -1);
130
        }
131
        else
132
        {
133
            $cost_percent_total = $method->cost_percent_total;
134
        }
135
136
        return ($method->cost_per_transaction + ($cart_prices['salesPrice'] * $cost_percent_total * 0.01));
137
    }
138
139
    /**
140
     * Check if the payment conditions are fulfilled for this payment method
141
     *
142
     * @param $cart
143
     * @param $method
144
     * @param $cart_prices
145
     *
146
     * @return boolean
147
     */
148
    protected function checkConditions($cart, $method, $cart_prices)
149
    {
150
        $this->convert($method);
151
        //         $params = new JParameter($payment->payment_params);
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
152
        $address = (($cart->ST == 0) ? $cart->BT : $cart->ST);
153
154
        $amount      = $cart_prices['salesPrice'];
155
        $amount_cond = ($amount >= $method->min_amount AND $amount <= $method->max_amount
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
156
            OR
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
157
            ($method->min_amount <= $amount AND ($method->max_amount == 0)));
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
158
        if (!$amount_cond)
159
        {
160
            return false;
161
        }
162
        $countries = array();
163
        if (!empty($method->countries))
164
        {
165
            if (!is_array($method->countries))
166
            {
167
                $countries[0] = $method->countries;
168
            }
169
            else
170
            {
171
                $countries = $method->countries;
172
            }
173
        }
174
175
        // probably did not gave his BT:ST address
176
        if (!is_array($address))
177
        {
178
            $address                          = array();
179
            $address['virtuemart_country_id'] = 0;
180
        }
181
182
        if (!isset($address['virtuemart_country_id']))
183
        {
184
            $address['virtuemart_country_id'] = 0;
185
        }
186
        if (count($countries) == 0 || in_array($address['virtuemart_country_id'], $countries) || count($countries) == 0)
187
        {
188
            return true;
189
        }
190
191
        return false;
192
    }
193
194
    /**
195
     * @param $method
196
     */
197
    function convert($method)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
198
    {
199
        $method->min_amount = (float)$method->min_amount;
200
        $method->max_amount = (float)$method->max_amount;
201
    }
202
203
    /*
204
     * We must reimplement this triggers for joomla 1.7
205
     */
206
207
    /**
208
     * Create the table for this plugin if it does not yet exist.
209
     * This functions checks if the called plugin is active one.
210
     * When yes it is calling the standard method to create the tables
211
     *
212
     * @param $jplugin_id
213
     *
214
     * @return
215
     */
216
    function plgVmOnStoreInstallPaymentPluginTable($jplugin_id)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
217
    {
218
        return $this->onStoreInstallPluginTable($jplugin_id);
219
    }
220
221
    /*
222
     * plgVmonSelectedCalculatePricePayment
223
     * Calculate the price (value, tax_id) of the selected method
224
     * It is called by the calculator
225
     * This function does NOT to be reimplemented. If not reimplemented, then the default values from this function are taken.
226
     *
227
     * @param VirtueMartCart $cart
228
     * @param array          $cart_prices
229
     * @param                $cart_prices_name
230
     *
231
     * @return
232
     */
233
234
    public function plgVmonSelectedCalculatePricePayment(VirtueMartCart $cart, array &$cart_prices, &$cart_prices_name)
235
    {
236
        return $this->onSelectedCalculatePrice($cart, $cart_prices, $cart_prices_name);
237
    }
238
239
    /**
240
     * @param $virtuemart_paymentmethod_id
241
     * @param $paymentCurrencyId
242
     *
243
     * @return
244
     */
245
    function plgVmgetPaymentCurrency($virtuemart_paymentmethod_id, &$paymentCurrencyId)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
246
    {
247
        if (!($method = $this->getVmPluginMethod($virtuemart_paymentmethod_id)))
248
        {
249
            return NULL; // Another method was selected, do nothing
250
        }
251
        if (!$this->selectedThisElement($method->payment_element))
252
        {
253
            return false;
254
        }
255
        $this->getPaymentCurrency($method);
256
257
        $paymentCurrencyId = $method->payment_currency;
258
        return;
259
    }
260
261
    /**
262
     * plgVmOnCheckAutomaticSelectedPayment
263
     * Checks how many plugins are available. If only one, the user will not have the choice. Enter edit_xxx page
264
     * The plugin must check first if it is the correct type
265
     *
266
     * @param VirtueMartCart $cart
267
     * @param array          $cart_prices
268
     * @param                $paymentCounter
269
     *
270
     * @return
271
     */
272
    function plgVmOnCheckAutomaticSelectedPayment(VirtueMartCart $cart, array $cart_prices = array(), &$paymentCounter)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
273
    {
274
        return $this->onCheckAutomaticSelected($cart, $cart_prices, $paymentCounter);
275
    }
276
277
    /**
278
     * This method is fired when showing the order details in the frontend.
279
     * It displays the method-specific data.
280
     *
281
     * @param $virtuemart_order_id
282
     * @param $virtuamart_paymentmethod_id
283
     * @param $payment_name
284
     */
285
    public function plgVmOnShowOrderFEPayment($virtuemart_order_id, $virtuemart_paymentmethod_id, &$payment_name)
286
    {
287
        $this->onShowOrderFE($virtuemart_order_id, $virtuemart_paymentmethod_id, $payment_name);
288
    }
289
290
    /**
291
     * This method is fired when showing when priting an Order
292
     * It displays the the payment method-specific data.
293
     *
294
     * @param integer $_virtuemart_order_id The order ID
0 ignored issues
show
Bug introduced by
There is no parameter named $_virtuemart_order_id. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
295
     * @param integer $method_id  method used for this order
296
     *
297
     * @return mixed Null when for payment methods that were not selected, text (HTML) otherwise
298
     */
299
    function plgVmonShowOrderPrintPayment($order_number, $method_id)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
300
    {
301
        return $this->onShowOrderPrint($order_number, $method_id);
302
    }
303
304
    /**
305
     * @param $name
306
     * @param $id
307
     * @param $data
308
     *
309
     * @return
310
     */
311
    function plgVmDeclarePluginParamsPayment($name, $id, &$data)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
312
    {
313
        return $this->declarePluginParams('payment', $name, $id, $data);
314
    }
315
    function plgVmDeclarePluginParamsPaymentVM3( &$data) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
316
        return $this->declarePluginParams('payment', $data);
317
    }
318
319
    /**
320
     * @param $name
321
     * @param $id
322
     * @param $table
323
     *
324
     * @return
325
     */
326
    function plgVmSetOnTablePluginParamsPayment($name, $id, &$table)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
327
    {
328
        return $this->setOnTablePluginParams($name, $id, $table);
329
    }
330
331
332
    /**
333
     * This event is fired by Offline Payment. It can be used to validate the payment data as entered by the user.
334
     *
335
     * @return
336
     */
337
    function plgVmOnPaymentNotification ()
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
338
    {
339 View Code Duplication
        if (!class_exists ('VirtueMartModelOrders'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
340
        {
341
            require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php');
342
        }
343
        $bitpay_data            = file_get_contents("php://input");
344
        $bitpay_data            = json_decode($bitpay_data, true);
345
346
        if (!isset($bitpay_data['id']))
347
        {
348
            bplog('no invoice in data');
349
            return NULL;
350
        }
351
352
        if (!isset($bitpay_data['posData']))
353
        {
354
            bplog('no invoice in data');
355
            return NULL;
356
        }
357
		$bitpay_pos_data = json_decode($bitpay_data['posData'], true);
358
        $order_number = $bitpay_pos_data['id_order'];
359
        if (!($virtuemart_order_id = VirtueMartModelOrders::getOrderIdByOrderNumber ($order_number)))
360
        {
361
            bplog('order not found '.$order_number);
362
            return NULL;
363
        }
364
365
        $modelOrder = VmModel::getModel ('orders');
366
        $order      = $modelOrder->getOrder($virtuemart_order_id);
367
        if (!$order)
368
        {
369
            bplog('order could not be loaded '.$virtuemart_order_id);
370
            return NULL;
371
        }
372
373
        $method = $this->getVmPluginMethod($order['details']['BT']->virtuemart_paymentmethod_id);
374
        if ($bitpay_pos_data['hash'] != crypt($order_number, $method->merchant_apikey))
375
        {
376
            bplog('api key invalid for order '.$order_number);
377
            return NULL;
378
        }
379
380
        // Call BitPay
381
        if ($method->network == "test")
382
        {
383
            $network_uri = 'test.bitpay.com';
384
        }
385
        else
386
        {
387
            $network_uri = 'bitpay.com';
388
        }
389
        $curl   = curl_init('https://' . $network_uri . '/api/invoice/'.$bitpay_data['id']);
390
        $length = 0;
391
392
        $uname  = base64_encode($method->merchant_apikey);
393
        $header = array(
394
            'Content-Type: application/json',
395
            "Content-Length: $length",
396
            "Authorization: Basic $uname",
397
            'X-BitPay-Plugin-Info: virtuemart073015',
398
        );
399
400
        curl_setopt($curl, CURLOPT_PORT, 443);
401
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
402
        curl_setopt($curl, CURLOPT_TIMEOUT, 10);
403
        curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ) ;
404
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1); // verify certificate
405
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // check existence of CN and verify that it matches hostname
406
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
407
        curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
408
        curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
409
410
        $responseString = curl_exec($curl);
411
412
        if($responseString == false)
413
        {
414
            return NULL;
415
        }
416
        else
417
        {
418
            $bitpay_data = json_decode($responseString, true);
419
        }
420
        curl_close($curl);
421
422
        $this->logInfo ('IPN ' . implode (' / ', $bitpay_data), 'message');
423
424
        if ($bitpay_data['status'] != 'confirmed' and $bitpay_data['status'] != 'complete')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
425
        {
426
            return NULL; // not the status we're looking for
427
        }
428
429
        $order['order_status'] = 'C'; // move to admin method option?
430
        $modelOrder->updateStatusForOneOrder ($virtuemart_order_id, $order, TRUE);
431
    }
432
433
    /**
434
     * @param $html
435
     *
436
     * @return bool|null|string
437
     */
438
    function plgVmOnPaymentResponseReceived (&$html)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
439
    {
440
        if (!class_exists ('VirtueMartCart'))
441
        {
442
            require(JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php');
443
        }
444
        if (!class_exists ('shopFunctionsF'))
445
        {
446
            require(JPATH_VM_SITE . DS . 'helpers' . DS . 'shopfunctionsf.php');
447
        }
448 View Code Duplication
        if (!class_exists ('VirtueMartModelOrders'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
449
        {
450
            require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php');
451
        }
452
453
        // the payment itself should send the parameter needed.
454
        $virtuemart_paymentmethod_id = JRequest::getInt ('pm', 0);
455
        $order_number                = JRequest::getString ('on', 0);
456
        $vendorId                    = 0;
0 ignored issues
show
Unused Code introduced by
$vendorId is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
457
458
        if (!($method = $this->getVmPluginMethod ($virtuemart_paymentmethod_id)))
459
        {
460
            return NULL; // Another method was selected, do nothing
461
        }
462
        if (!$this->selectedThisElement ($method->payment_element))
463
        {
464
            return NULL;
465
        }
466
467
        if (!($virtuemart_order_id = VirtueMartModelOrders::getOrderIdByOrderNumber ($order_number)))
468
        {
469
            return NULL;
470
        }
471
        if (!($paymentTable = $this->getDataByOrderId ($virtuemart_order_id)))
472
        {
473
            // JError::raiseWarning(500, $db->getErrorMsg());
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
474
            return '';
475
        }
476
        $payment_name = $this->renderPluginName ($method);
477
        $html         = $this->_getPaymentResponseHtml ($paymentTable, $payment_name);
478
479
        //We delete the old stuff
480
        // get the correct cart / session
481
        return TRUE;
482
    }
483
484
    /**
485
     * This shows the plugin for choosing in the payment list of the checkout process.
486
     *
487
     * @param VirtueMartCart $cart
488
     * @param integer        $selected
489
     * @param                $htmlIn
490
     *
491
     * @return
492
     */
493
    function plgVmDisplayListFEPayment (VirtueMartCart $cart, $selected = 0, &$htmlIn)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
494
    {
495
        $session = JFactory::getSession ();
496
        $errors  = $session->get ('errorMessages', 0, 'vm');
497
498
        if($errors != "")
499
        {
500
            $errors = unserialize($errors);
0 ignored issues
show
Unused Code introduced by
$errors is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
501
            $session->set ('errorMessages', "", 'vm');
502
        }
503
        else
504
        {
505
            $errors = array();
0 ignored issues
show
Unused Code introduced by
$errors is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
506
        }
507
508
        return $this->displayListFE ($cart, $selected, $htmlIn);
509
    }
510
511
    /**
512
     * getGMTTimeStamp:
513
     *
514
     * this function creates a timestamp formatted as per requirement in the
515
     * documentation
516
     *
517
     * @return string The formatted timestamp
518
     */
519
    public function getGMTTimeStamp()
520
    {
521
        /* Format: YYYYDDMMHHNNSSKKK000sOOO
522
            YYYY is a 4-digit year
523
            DD is a 2-digit zero-padded day of month
524
            MM is a 2-digit zero-padded month of year (January = 01)
525
            HH is a 2-digit zero-padded hour of day in 24-hour clock format (midnight =0)
526
            NN is a 2-digit zero-padded minute of hour
527
            SS is a 2-digit zero-padded second of minute
528
            KKK is a 3-digit zero-padded millisecond of second
529
            000 is a Static 0 characters, as BitPay does not store nanoseconds
530
            sOOO is a Time zone offset, where s is + or -, and OOO = minutes, from GMT.
531
         */
532
        $tz_minutes = date('Z') / 60;
533
534
        if ($tz_minutes >= 0)
535
        {
536
            $tz_minutes = '+' . sprintf("%03d",$tz_minutes); //Zero padding in-case $tz_minutes is 0
537
        }
538
539
        $stamp = date('YdmHis000000') . $tz_minutes; //In some locales, in some situations (i.e. Magento 1.4.0.1) some digits are missing. Added 5 zeroes and truncating to the required length. Terrible terrible hack.
540
541
        return $stamp;
542
    }
543
544
    /**
545
     * @param       $data
546
     * @param array $outputArray
547
     *
548
     * @return
549
     */
550
    private function makeXMLTree ($data, &$outputArray = array())
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
551
    {
552
        $parser = xml_parser_create();
553
        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
554
        xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
555
        $result = xml_parse_into_struct($parser, $data, $values, $tags);
556
        xml_parser_free($parser);
557
        if ($result == 0)
558
        {
559
            return false;
560
        }
561
562
        $hash_stack = array();
563
        foreach ($values as $key => $val)
564
        {
565
            switch ($val['type'])
566
            {
567
            case 'open':
568
                array_push($hash_stack, $val['tag']);
569
                break;
570
            case 'close':
571
                array_pop($hash_stack);
572
                break;
573
            case 'complete':
574
                array_push($hash_stack, $val['tag']);
575
                // ATTN, I really hope this is sanitized
576
                eval("\$outputArray['" . implode($hash_stack, "']['") . "'] = \"{$val['value']}\";");
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
577
                array_pop($hash_stack);
578
                break;
579
            }
580
        }
581
582
        return true;
583
    }
584
585
    /**
586
     * @param $cart
587
     * @param $order
588
     *
589
     * @return
590
     */
591
    function plgVmConfirmedOrder($cart, $order)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
592
    {
593
        if (!($method = $this->getVmPluginMethod($order['details']['BT']->virtuemart_paymentmethod_id)))
594
        {
595
            return NULL; // Another method was selected, do nothing
596
        }
597
        if (!$this->selectedThisElement($method->payment_element))
598
        {
599
            return false;
600
        }
601
        //         $params = new JParameter($payment->payment_params);
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
602
        // $lang     = JFactory::getLanguage();
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
603
        // $filename = 'com_virtuemart';
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
604
        // $lang->load($filename, JPATH_ADMINISTRATOR);
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
605
        $vendorId = 0;
606
        $html     = "";
607
608
        VmConfig::loadJLang('com_virtuemart',true);
609
        VmConfig::loadJLang('com_virtuemart_orders', TRUE);
610
611
        $this->getPaymentCurrency($method);
612
613
614 View Code Duplication
        if (!class_exists('VirtueMartModelOrders'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
615
        {
616
            require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php');
617
        }
618
619
        $this->getPaymentCurrency($method, true);
620
        $currency_code_3 = shopFunctions::getCurrencyByID($method->payment_currency, 'currency_code_3');
621
        $email_currency = $this->getEmailCurrency($method);
0 ignored issues
show
Unused Code introduced by
$email_currency is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
622
623
624
        // END printing out HTML Form code (Payment Extra Info)
625
        $q  = 'SELECT `currency_code_3` FROM `#__virtuemart_currencies` WHERE `virtuemart_currency_id`="' . $method->payment_currency . '" ';
626
        $db = JFactory::getDBO();
627
        $db->setQuery($q);
628
        $paymentCurrency        = CurrencyDisplay::getInstance($method->payment_currency);
629
        $totalInPaymentCurrency = round($paymentCurrency->convertCurrencyTo($method->payment_currency, $order['details']['BT']->order_total, false), 2);
0 ignored issues
show
Unused Code introduced by
$totalInPaymentCurrency is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
630
        $cd                     = CurrencyDisplay::getInstance($cart->pricesCurrency);
0 ignored issues
show
Unused Code introduced by
$cd is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
631
        $usrBT                  = $order['details']['BT'];
0 ignored issues
show
Unused Code introduced by
$usrBT is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
632
        $usrST                  = ((isset($order['details']['ST'])) ? $order['details']['ST'] : $order['details']['BT']);
0 ignored issues
show
Unused Code introduced by
$usrST is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
633
634
        $options['transactionSpeed'] = $method->speed;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
635
        $options['currency']         = $currency_code_3;
636
        $options['notificationURL']  = (JROUTE::_ (JURI::root () . 'index.php?option=com_virtuemart&view=pluginresponse&task=pluginnotification&tmpl=component'));
637
        $options['redirectURL']      = (JROUTE::_ (JURI::root () . 'index.php?option=com_virtuemart&view=pluginresponse&task=pluginresponsereceived&on=' . $order['details']['BT']->order_number . '&pm=' . $order['details']['BT']->virtuemart_paymentmethod_id . '&Itemid=' . JRequest::getInt ('Itemid')));
638
        $options['posData']          = '{"id_order": "' . $order['details']['BT']->order_number . '"';
639
        $options['posData']         .= ', "hash": "' . crypt($order['details']['BT']->order_number, $method->merchant_apikey) . '"';
640
        $options['posData']         .= '}';
641
        $options['orderID']          = $order['details']['BT']->order_number;
642
        $options['price']            = $order['details']['BT']->order_total;
643
644
645
        $postOptions = array('orderID', 'itemDesc', 'itemCode', 'notificationEmail', 'notificationURL', 'redirectURL',
646
            'posData', 'price', 'currency', 'physical', 'fullNotifications', 'transactionSpeed', 'buyerName',
647
            'buyerAddress1', 'buyerAddress2', 'buyerCity', 'buyerState', 'buyerZip', 'buyerEmail', 'buyerPhone');
648
649
        foreach($postOptions as $o)
650
        {
651
            if (array_key_exists($o, $options))
652
            {
653
                $post[$o] = $options[$o];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$post was never initialized. Although not strictly required by PHP, it is generally a good practice to add $post = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
654
            }
655
        }
656
657
        $post = json_encode($post);
0 ignored issues
show
Bug introduced by
The variable $post does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
658
659
        // Call BitPay
660
        if ($method->network == "test")
661
        {
662
            $network_uri = 'test.bitpay.com';
663
        }
664
        else
665
        {
666
            $network_uri = 'bitpay.com';
667
        }
668
        $curl   = curl_init('https://' . $network_uri . '/api/invoice/');
669
        $length = 0;
670
        if ($post)
671
        {
672
            curl_setopt($curl, CURLOPT_POST, 1);
673
            curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
674
            $length = strlen($post);
675
        }
676
677
        $uname  = base64_encode($method->merchant_apikey);
678
        $header = array(
679
            'Content-Type: application/json',
680
            "Content-Length: $length",
681
            "Authorization: Basic $uname",
682
            'X-BitPay-Plugin-Info: virtuemart073015',
683
        );
684
685
        curl_setopt($curl, CURLOPT_PORT, 443);
686
        curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
687
        curl_setopt($curl, CURLOPT_TIMEOUT, 10);
688
        curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC ) ;
689
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1); // verify certificate
690
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // check existence of CN and verify that it matches hostname
691
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
692
        curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
693
        curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
694
695
        $responseString = curl_exec($curl);
696
697
        if($responseString == false)
698
        {
699
700
            $response = curl_error($curl);
701
        }
702
        else
703
        {
704
            $response = json_decode($responseString, true);
705
        }
706
        curl_close($curl);
707
708
        $this->logInfo ('invoice ' . implode (' / ', $response), 'message');
709
        if (isset($response['url']))
710
        {
711
            $cart->emptyCart ();
712
            header('Location: ' . $response['url']);
713
            exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method plgVmConfirmedOrder() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
714
        }
715
        else
716
        {
717
            $html = vmText::_ ('BitPay could not process your payment for the following reasons:') .
718
                " <br /> -------------------- "  . "<br />" .
719
                vmText::_ ($response['error']['message']) . "<br /> " .
720
                vmText::_ ('Please contact the store owner');
721
            bplog("VM BitPayError: " . $response['error']['message'] . " with order id: " . $order['details']['BT']->order_number);
722
            bplog('curl error - no invoice url');
723
724
            $returnValue = 0;
725
            return $this->processConfirmedOrderPaymentResponse ($returnValue, $cart, $order, $html, '', '');
726
        }
727
    }
728
729
    /**
730
     * @param $virtualmart_order_id
731
     * @param $html
732
     */
733
    function _handlePaymentCancel ($virtuemart_order_id, $html)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
734
    {
735 View Code Duplication
        if (!class_exists ('VirtueMartModelOrders'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
736
        {
737
            require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php');
738
        }
739
        $modelOrder = VmModel::getModel ('orders');
740
        $modelOrder->remove (array('virtuemart_order_id' => $virtuemart_order_id));
741
        // error while processing the payment
742
        $mainframe = JFactory::getApplication ();
743
        $mainframe->redirect (JRoute::_ ('index.php?option=com_virtuemart&view=cart&task=editpayment'), $html);
744
    }
745
746
    /**
747
     * takes a string and returns an array of characters
748
     *
749
     * @param string $input string of characters
750
     * @return array
751
     */
752
    function toCharArray($input)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
753
    {
754
        $len = strlen ( $input );
755
        for($j = 0; $j < $len; $j ++)
756
        {
757
            $char [$j] = substr ( $input, $j, 1 );
0 ignored issues
show
Coding Style Comprehensibility introduced by
$char was never initialized. Although not strictly required by PHP, it is generally a good practice to add $char = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
758
        }
759
        return ($char);
0 ignored issues
show
Bug introduced by
The variable $char does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
760
    }
761
    /**
762
     * @param $virtuemart_paymentmethod_id
763
     * @param $paymentCurrencyId
764
     * @return bool|null
765
     */
766
    function plgVmgetEmailCurrency($virtuemart_paymentmethod_id, $virtuemart_order_id, &$emailCurrencyId) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
767
        if (!($method = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) {
768
            return NULL; // Another method was selected, do nothing
769
        }
770
        if (!$this->selectedThisElement($method->payment_element)) {
771
            return FALSE;
772
        }
773
        if (!($payments = $this->getDatasByOrderId($virtuemart_order_id))) {
774
            // JError::raiseWarning(500, $db->getErrorMsg());
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
775
            return '';
776
        }
777
        if (empty($payments[0]->email_currency)) {
778
            $vendorId = 1; //VirtueMartModelVendor::getLoggedVendor();
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
779
            $db = JFactory::getDBO();
780
            $q = 'SELECT   `vendor_currency` FROM `#__virtuemart_vendors` WHERE `virtuemart_vendor_id`=' . $vendorId;
781
            $db->setQuery($q);
782
            $emailCurrencyId = $db->loadResult();
783
        } else {
784
            $emailCurrencyId = $payments[0]->email_currency;
785
        }
786
    }
787
}
788
789
defined('_JEXEC') or die('Restricted access');
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
790
791
/*
792
 * This class is used by VirtueMart Payment  Plugins
793
 * which uses JParameter
794
 * So It should be an extension of JElement
795
 * Those plugins cannot be configured througth the Plugin Manager anyway.
796
 */
797
if (!class_exists( 'VmConfig' ))
798
{
799
    require(JPATH_ADMINISTRATOR . DS . 'components' . DS . 'com_virtuemart'.DS.'helpers'.DS.'config.php');
800
}
801
if (!class_exists('ShopFunctions'))
802
{
803
    require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'shopfunctions.php');
804
}
805
806
// Check to ensure this file is within the rest of the framework
807
defined('JPATH_BASE') or die();
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
808