1
|
|
|
<?php
|
|
|
|
|
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');
|
|
|
|
|
32
|
|
|
|
33
|
|
|
if (!class_exists('vmPSPlugin'))
|
34
|
|
|
{
|
35
|
|
|
require(JPATH_VM_PLUGINS . DS . 'vmpsplugin.php');
|
36
|
|
|
}
|
37
|
|
|
|
38
|
|
|
class plgVmPaymentBitPay extends vmPSPlugin
|
|
|
|
|
39
|
|
|
{
|
40
|
|
|
|
41
|
|
|
/**
|
42
|
|
|
* @param $subject
|
43
|
|
|
* @param $config
|
44
|
|
|
*/
|
45
|
|
|
function __construct(&$subject, $config)
|
|
|
|
|
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()
|
|
|
|
|
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)
|
|
|
|
|
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)
|
|
|
|
|
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);
|
|
|
|
|
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
|
|
|
|
|
156
|
|
|
OR
|
|
|
|
|
157
|
|
|
($method->min_amount <= $amount AND ($method->max_amount == 0)));
|
|
|
|
|
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)
|
|
|
|
|
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)
|
|
|
|
|
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)
|
|
|
|
|
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)
|
|
|
|
|
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
|
|
|
|
|
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)
|
|
|
|
|
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)
|
|
|
|
|
312
|
|
|
{
|
313
|
|
|
return $this->declarePluginParams('payment', $name, $id, $data);
|
314
|
|
|
}
|
315
|
|
|
function plgVmDeclarePluginParamsPaymentVM3( &$data) {
|
|
|
|
|
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)
|
|
|
|
|
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 ()
|
|
|
|
|
338
|
|
|
{
|
339
|
|
View Code Duplication |
if (!class_exists ('VirtueMartModelOrders'))
|
|
|
|
|
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')
|
|
|
|
|
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)
|
|
|
|
|
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'))
|
|
|
|
|
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;
|
|
|
|
|
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());
|
|
|
|
|
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)
|
|
|
|
|
494
|
|
|
{
|
495
|
|
|
$session = JFactory::getSession ();
|
496
|
|
|
$errors = $session->get ('errorMessages', 0, 'vm');
|
497
|
|
|
|
498
|
|
|
if($errors != "")
|
499
|
|
|
{
|
500
|
|
|
$errors = unserialize($errors);
|
|
|
|
|
501
|
|
|
$session->set ('errorMessages', "", 'vm');
|
502
|
|
|
}
|
503
|
|
|
else
|
504
|
|
|
{
|
505
|
|
|
$errors = array();
|
|
|
|
|
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())
|
|
|
|
|
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']}\";");
|
|
|
|
|
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)
|
|
|
|
|
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);
|
|
|
|
|
602
|
|
|
// $lang = JFactory::getLanguage();
|
|
|
|
|
603
|
|
|
// $filename = 'com_virtuemart';
|
|
|
|
|
604
|
|
|
// $lang->load($filename, JPATH_ADMINISTRATOR);
|
|
|
|
|
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'))
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
630
|
|
|
$cd = CurrencyDisplay::getInstance($cart->pricesCurrency);
|
|
|
|
|
631
|
|
|
$usrBT = $order['details']['BT'];
|
|
|
|
|
632
|
|
|
$usrST = ((isset($order['details']['ST'])) ? $order['details']['ST'] : $order['details']['BT']);
|
|
|
|
|
633
|
|
|
|
634
|
|
|
$options['transactionSpeed'] = $method->speed;
|
|
|
|
|
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];
|
|
|
|
|
654
|
|
|
}
|
655
|
|
|
}
|
656
|
|
|
|
657
|
|
|
$post = json_encode($post);
|
|
|
|
|
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;
|
|
|
|
|
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)
|
|
|
|
|
734
|
|
|
{
|
735
|
|
View Code Duplication |
if (!class_exists ('VirtueMartModelOrders'))
|
|
|
|
|
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)
|
|
|
|
|
753
|
|
|
{
|
754
|
|
|
$len = strlen ( $input );
|
755
|
|
|
for($j = 0; $j < $len; $j ++)
|
756
|
|
|
{
|
757
|
|
|
$char [$j] = substr ( $input, $j, 1 );
|
|
|
|
|
758
|
|
|
}
|
759
|
|
|
return ($char);
|
|
|
|
|
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) {
|
|
|
|
|
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());
|
|
|
|
|
775
|
|
|
return '';
|
776
|
|
|
}
|
777
|
|
|
if (empty($payments[0]->email_currency)) {
|
778
|
|
|
$vendorId = 1; //VirtueMartModelVendor::getLoggedVendor();
|
|
|
|
|
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');
|
|
|
|
|
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();
|
|
|
|
|
808
|
|
|
|
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.