PageRenderTime 62ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/administrator/components/com_virtuemart/classes/ps_checkout.php

https://bitbucket.org/dgough/annamaria-daneswood-25102012
PHP | 2545 lines | 1679 code | 381 blank | 485 comment | 361 complexity | f85fbf354a3c8b6a921b904dbf3d7aeb MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. if( !defined( '_VALID_MOS' ) && !defined( '_JEXEC' ) ) die( 'Direct Access to '.basename(__FILE__).' is not allowed.' );
  3. /**
  4. *
  5. * @version $Id: ps_checkout.php 1451 2008-07-04 19:55:31Z soeren_nb $
  6. * @package VirtueMart
  7. * @subpackage classes
  8. * @copyright Copyright (C) 2004-2008 soeren - All rights reserved.
  9. * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php
  10. * VirtueMart is free software. This version may have been modified pursuant
  11. * to the GNU General Public License, and as distributed it includes or
  12. * is derivative of works licensed under the GNU General Public License or
  13. * other free or open source software licenses.
  14. * See /administrator/components/com_virtuemart/COPYRIGHT.php for copyright notices and details.
  15. *
  16. * http://virtuemart.net
  17. */
  18. define("CHECK_OUT_GET_FINAL_BASKET", 1);
  19. define("CHECK_OUT_GET_SHIPPING_ADDR", 2);
  20. define("CHECK_OUT_GET_SHIPPING_METHOD", 3);
  21. define("CHECK_OUT_GET_PAYMENT_METHOD", 4);
  22. define("CHECK_OUT_GET_FINAL_CONFIRMATION", 99);
  23. /**
  24. * The class contains the shop checkout code. It is used to checkout
  25. * and order and collect payment information.
  26. *
  27. */
  28. class ps_checkout {
  29. var $_SHIPPING = null;
  30. var $_subtotal = null;
  31. var $_shipping = null;
  32. var $_shipping_tax = null;
  33. var $_payment_discount = null;
  34. var $_coupon_discount = null;
  35. var $_order_total = null;
  36. /** @var string An md5 hash of print_r( $cart, true ) to check wether the checkout values have to be renewed */
  37. var $_cartHash;
  38. /**
  39. * Initiate Shipping Modules
  40. */
  41. function ps_checkout() {
  42. global $vendor_freeshipping, $vars, $PSHOP_SHIPPING_MODULES;
  43. // Make a snapshot of the current checkout configuration
  44. $this->generate_cart_hash();
  45. /* Ok, need to decide if we have a free Shipping amount > 0,
  46. * and IF the cart total is more than that Free Shipping amount,
  47. * let's set Order Shipping = 0
  48. */
  49. $this->_subtotal = $this->get_order_subtotal($vars);
  50. if( $vendor_freeshipping > 0 && $vars['order_subtotal_withtax'] >= $vendor_freeshipping) {
  51. $PSHOP_SHIPPING_MODULES = Array( "free_shipping" );
  52. include_once( CLASSPATH. "shipping/free_shipping.php" );
  53. $this->_SHIPPING = new free_shipping();
  54. }
  55. elseif( !empty( $_REQUEST['shipping_rate_id'] )) {
  56. // Create a Shipping Object and assign it to the _SHIPPING attribute
  57. // We take the first Part of the Shipping Rate Id String
  58. // which holds the Class Name of the Shipping Module
  59. $rate_array = explode( "|", urldecode(vmGet($_REQUEST,"shipping_rate_id")) );
  60. $filename = basename( $rate_array[0] );
  61. if( $filename != '' && file_exists(CLASSPATH. "shipping/".$filename.".php")) {
  62. include_once( CLASSPATH. "shipping/".$filename.".php" );
  63. if( class_exists($filename) ) {
  64. $this->_SHIPPING =& new $filename();
  65. }
  66. }
  67. }
  68. //$steps = ps_checkout::get_checkout_steps();
  69. if(empty($_REQUEST['ship_to_info_id']) && ps_checkout::noShipToNecessary()) {
  70. $db = new ps_DB();
  71. /* Select all the ship to information for this user id and
  72. * order by modification date; most recently changed to oldest
  73. */
  74. $q = "SELECT user_info_id from `#__{vm}_user_info` WHERE ";
  75. $q .= "user_id='" . $_SESSION['auth']["user_id"] . "' ";
  76. $q .= "AND address_type='BT'";
  77. $db->query($q);
  78. $db->next_record();
  79. $_REQUEST['ship_to_info_id'] = $db->f("user_info_id");
  80. }
  81. }
  82. /**
  83. * Checks if Ship To can be skipped
  84. *
  85. * @return boolean
  86. */
  87. function noShipToNecessary() {
  88. global $cart, $only_downloadable_products;
  89. if( NO_SHIPTO == '1') {
  90. return true;
  91. }
  92. if( !isset( $cart)) $cart = ps_cart::initCart();
  93. if( ENABLE_DOWNLOADS == '1') {
  94. $not_downloadable = false;
  95. require_once( CLASSPATH .'ps_product.php');
  96. for($i = 0; $i < $cart["idx"]; $i++) {
  97. if( !ps_product::is_downloadable($cart[$i]['product_id']) ) {
  98. $not_downloadable = true;
  99. break;
  100. }
  101. }
  102. return !$not_downloadable;
  103. }
  104. return false;
  105. }
  106. function noShippingMethodNecessary() {
  107. global $cart, $only_downloadable_products;
  108. if( NO_SHIPPING == '1') {
  109. return true;
  110. }
  111. if( !isset( $cart)) $cart = ps_cart::initCart();
  112. if( ENABLE_DOWNLOADS == '1') {
  113. $not_downloadable = false;
  114. require_once( CLASSPATH .'ps_product.php');
  115. for($i = 0; $i < $cart["idx"]; $i++) {
  116. if( !ps_product::is_downloadable($cart[$i]['product_id']) ) {
  117. $not_downloadable = true;
  118. break;
  119. }
  120. }
  121. return !$not_downloadable;
  122. }
  123. return false;
  124. }
  125. function noShippingNecessary() {
  126. return $this->noShipToNecessary() && $this->noShippingMethodNecessary();
  127. }
  128. /**
  129. * Retrieve an array with all order steps and their details
  130. *
  131. * @return array
  132. */
  133. function get_checkout_steps() {
  134. global $VM_CHECKOUT_MODULES;
  135. $stepnames = array_keys( $VM_CHECKOUT_MODULES );
  136. $steps = array();
  137. $i = 0;
  138. $last_order = 0;
  139. foreach( $VM_CHECKOUT_MODULES as $step ) {
  140. // Get the stepname from the array key
  141. $stepname = current($stepnames);
  142. next($stepnames);
  143. switch( $stepname ) {
  144. case 'CHECK_OUT_GET_SHIPPING_ADDR':
  145. if( ps_checkout::noShipToNecessary() ) $step['enabled'] = 0;
  146. break;
  147. case 'CHECK_OUT_GET_SHIPPING_METHOD':
  148. if( ps_checkout::noShippingMethodNecessary() ) $step['enabled'] = 0;
  149. break;
  150. }
  151. if( $step['enabled'] == 1 ) {
  152. $steps[$step['order']][] = $stepname;
  153. }
  154. }
  155. ksort( $steps );
  156. return $steps;
  157. }
  158. /**
  159. * Retrieve the key name of the current checkout step
  160. *
  161. * @return string
  162. */
  163. function get_current_stage() {
  164. $steps = ps_checkout::get_checkout_steps();
  165. $stage = key( $steps ); // $steps is sorted by key, so the first key is the first stage
  166. // First check the REQUEST parameters for other steps
  167. if( !empty( $_REQUEST['checkout_last_step'] ) && empty( $_POST['checkout_this_step'] )) {
  168. // Make sure we have an integer (max 4)
  169. $checkout_step = abs( min( $_REQUEST['checkout_last_step'], 4 ) );
  170. if( isset( $steps[$checkout_step] )) {
  171. return $checkout_step; // it's a valid step
  172. }
  173. }
  174. $checkout_step = (int)vmGet( $_REQUEST, 'checkout_stage' );
  175. if( isset( $steps[$checkout_step] )) {
  176. return $checkout_step; // it's a valid step
  177. }
  178. // Else: we have no alternative steps given by REQUEST
  179. while ($step = current($steps)) {
  180. if( !empty($_POST['checkout_this_step']) ) {
  181. foreach( $step as $stepname ) {
  182. if( in_array( $stepname, $_POST['checkout_this_step'])) {
  183. next($steps);
  184. $key = key( $steps );
  185. if( empty( $key )) {
  186. // We are beyond the last index of the array and need to go "back" to the last index
  187. end( $steps );
  188. }
  189. //echo "Stage: ".key( $steps );
  190. return key($steps);
  191. }
  192. }
  193. }
  194. next($steps);
  195. }
  196. return $stage;
  197. }
  198. /**
  199. * Displays the "checkout bar" using the checkout bar template
  200. *
  201. * @param array $steps_to_do Array holding all steps the customer has to make
  202. * @param array $step_msg Array containing the step messages
  203. * @param int $step_count Number of steps to make
  204. * @param int $highlighted_step The index of the recent step
  205. */
  206. function show_checkout_bar() {
  207. global $sess, $ship_to_info_id, $shipping_rate_id, $VM_LANG;
  208. if (SHOW_CHECKOUT_BAR != '1' || defined('VM_CHECKOUT_BAR_LOADED')) {
  209. return;
  210. }
  211. // Let's assemble the steps
  212. $steps = ps_checkout::get_checkout_steps();
  213. $step_count = sizeof( $steps );
  214. $steps_tmp = $steps;
  215. $i = 0;
  216. foreach( $steps as $step ) {
  217. foreach( $step as $step_name ) {
  218. switch ( $step_name ) {
  219. case 'CHECK_OUT_GET_SHIPPING_ADDR':
  220. $step_msg = $VM_LANG->_('PHPSHOP_ADD_SHIPTO_2');
  221. break;
  222. case 'CHECK_OUT_GET_SHIPPING_METHOD':
  223. $step_msg = $VM_LANG->_('PHPSHOP_ISSHIP_LIST_CARRIER_LBL');
  224. break;
  225. case 'CHECK_OUT_GET_PAYMENT_METHOD':
  226. $step_msg = $VM_LANG->_('PHPSHOP_ORDER_PRINT_PAYMENT_LBL');
  227. break;
  228. case 'CHECK_OUT_GET_FINAL_CONFIRMATION':
  229. $step_msg = $VM_LANG->_('PHPSHOP_CHECKOUT_CONF_PAYINFO_COMPORDER');
  230. break;
  231. }
  232. $steps_to_do[$i][] = array('step_name' => $step_name,
  233. 'step_msg' => $step_msg,
  234. 'step_order' => key($steps_tmp) );
  235. }
  236. next( $steps_tmp );
  237. $i++;
  238. }
  239. $highlighted_step = ps_checkout::get_current_stage();
  240. $theme = new $GLOBALS['VM_THEMECLASS']();
  241. $theme->set_vars( array( 'step_count' => $step_count,
  242. 'steps_to_do' => $steps_to_do,
  243. 'steps' => $steps,
  244. 'highlighted_step' => $highlighted_step,
  245. 'ship_to_info_id' => vmGet($_REQUEST, 'ship_to_info_id'),
  246. 'shipping_rate_id' => vmGet( $_REQUEST, 'shipping_rate_id')
  247. ) );
  248. echo $theme->fetch( 'checkout/checkout_bar.tpl.php');
  249. define('VM_CHECKOUT_BAR_LOADED', 1 );
  250. }
  251. /**
  252. * Called to validate the form values before the order is stored
  253. *
  254. * @author gday
  255. * @author soeren
  256. *
  257. * @param array $d
  258. * @return boolean
  259. */
  260. function validate_form(&$d) {
  261. global $VM_LANG, $PSHOP_SHIPPING_MODULES, $vmLogger;
  262. $db = new ps_DB;
  263. $auth = $_SESSION['auth'];
  264. $cart = $_SESSION['cart'];
  265. if (!$cart["idx"]) {
  266. $q = "SELECT order_id FROM #__{vm}_orders WHERE user_id='" . $auth["user_id"] . "' ";
  267. $q .= "ORDER BY cdate DESC";
  268. $db->query($q);
  269. $db->next_record();
  270. $d["order_id"] = $db->f("order_id");
  271. return False;
  272. }
  273. if( PSHOP_AGREE_TO_TOS_ONORDER == '1' ) {
  274. if( empty( $d["agreed"] )) {
  275. $vmLogger->warning( $VM_LANG->_('PHPSHOP_AGREE_TO_TOS',false) );
  276. return false;
  277. }
  278. }
  279. if ( !ps_checkout::noShippingMethodNecessary() ) {
  280. if ( !$this->validate_shipping_method($d) ) {
  281. return False;
  282. }
  283. }
  284. if ( !$this->validate_payment_method( $d, false )) {
  285. return false;
  286. }
  287. if( CHECK_STOCK == '1' ) {
  288. for($i = 0; $i < $cart["idx"]; $i++) {
  289. $quantity_in_stock = ps_product::get_field($cart[$i]["product_id"], 'product_in_stock');
  290. $product_name = ps_product::get_field($cart[$i]["product_id"], 'product_name');
  291. if( $cart[$i]["quantity"] > $quantity_in_stock ) {
  292. $vmLogger->err( 'The Quantity for the Product "'.$product_name.'" in your Cart ('.$cart[$i]["quantity"].') exceeds the Quantity in Stock ('.$quantity_in_stock.').
  293. We are very sorry for this Inconvenience, but you you need to lower the Quantity in Cart for this Product.');
  294. return false;
  295. }
  296. }
  297. }
  298. return True;
  299. }
  300. /**
  301. * Validates the variables prior to adding an order
  302. *
  303. * @param array $d
  304. * @return boolean
  305. */
  306. function validate_add(&$d) {
  307. global $auth, $VM_LANG, $vmLogger;
  308. require_once(CLASSPATH.'ps_payment_method.php');
  309. $ps_payment_method = new ps_payment_method;
  310. if( empty( $auth['user_id'] ) ) {
  311. $vmLogger->err('Sorry, but it is not possible to order without a User ID.
  312. Please contact the Store Administrator if this Error occurs again.');
  313. return false;
  314. }
  315. if (!ps_checkout::noShipToNecessary()) {
  316. if (empty($d["ship_to_info_id"])) {
  317. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_SHIPTO',false) );
  318. return False;
  319. }
  320. }
  321. /*
  322. if (!$d["payment_method_id"]) {
  323. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_MSG_4',false) );
  324. return False;
  325. }*/
  326. if ($ps_payment_method->is_creditcard(@$d["payment_method_id"])) {
  327. if (empty($_SESSION["ccdata"]["order_payment_number"])) {
  328. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_CCNR',false) );
  329. return False;
  330. }
  331. if(!$ps_payment_method->validate_payment($d["payment_method_id"],
  332. $_SESSION["ccdata"]["order_payment_number"])) {
  333. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_CCNUM_INV',false) );
  334. return False;
  335. }
  336. if(empty($_SESSION['ccdata']['order_payment_expire'])) {
  337. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_CCDATE_INV',false) );
  338. return False;
  339. }
  340. }
  341. return True;
  342. }
  343. function validate_shipto(&$d) {
  344. //TODO to be implemented
  345. }
  346. /**
  347. * Called to validate the shipping_method
  348. *
  349. * @param array $d
  350. * @return boolean
  351. */
  352. function validate_shipping_method(&$d) {
  353. global $VM_LANG, $PSHOP_SHIPPING_MODULES, $vmLogger;
  354. if( empty($d['shipping_rate_id']) ) {
  355. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_SHIP',false) );
  356. return false;
  357. }
  358. if( is_callable( array($this->_SHIPPING, 'validate') )) {
  359. if(!$this->_SHIPPING->validate( $d )) {
  360. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_OTHER_SHIP',false) );
  361. return false;
  362. }
  363. }
  364. return true;
  365. }
  366. /**
  367. * Called to validate the payment_method
  368. * If payment with CreditCard is used, than the Data must be in stored in the session
  369. * This has be done to prevent sending the CreditCard Number back in hidden fields
  370. * If the parameter $is_test is true the Number Visa Creditcard number 4111 1111 1111 1111
  371. *
  372. * @param array $d
  373. * @param boolean $is_test
  374. * @return boolean
  375. */
  376. function validate_payment_method(&$d, $is_test) {
  377. global $VM_LANG, $vmLogger, $order_total;
  378. $auth = $_SESSION['auth'];
  379. $cart = $_SESSION['cart'];
  380. // We don't need to validate a payment method when
  381. // the user has no order total he should pay
  382. if( empty( $_REQUEST['order_total'])) {
  383. if( isset( $d['order_total'])) {
  384. if( round( $d['order_total'], 2 ) <= 0.00 ) {
  385. return true;
  386. }
  387. }
  388. if( isset($order_total) && $order_total <= 0.00 ) {
  389. return true;
  390. }
  391. }
  392. if (!isset($d["payment_method_id"]) || $d["payment_method_id"]==0 ) {
  393. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_PAYM',false) );
  394. return false;
  395. }
  396. require_once(CLASSPATH.'ps_payment_method.php');
  397. $ps_payment_method = new ps_payment_method;
  398. $dbp = new ps_DB; //DB Payment_method
  399. // Now Check if all needed Payment Information are entered
  400. // Bank Information is found in the User_Info
  401. $w = "SELECT `enable_processor` FROM `#__{vm}_payment_method` WHERE ";
  402. $w .= "payment_method_id=" . (int)$d["payment_method_id"];
  403. $dbp->query($w);
  404. $dbp->next_record();
  405. if (($dbp->f("enable_processor") == "Y")
  406. || ($dbp->f("enable_processor") == "")) {
  407. // Creditcard
  408. if (empty( $_SESSION['ccdata']['creditcard_code']) ) {
  409. $vmLogger->err( $VM_LANG->_('VM_CHECKOUT_ERR_CCTYPE') );
  410. return false;
  411. }
  412. // $_SESSION['ccdata'] = $ccdata;
  413. // The Data should be in the session
  414. if (!isset($_SESSION['ccdata'])) { //Not? Then Error
  415. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_CCDATA',false) );
  416. return False;
  417. }
  418. if (!$_SESSION['ccdata']['order_payment_number']) {
  419. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_CCNR_FOUND',false) );
  420. return False;
  421. }
  422. // CREDIT CARD NUMBER CHECK
  423. // USING THE CREDIT CARD CLASS in ps_payment
  424. if(!$ps_payment_method->validate_payment( $_SESSION['ccdata']['creditcard_code'], $_SESSION['ccdata']['order_payment_number'])) {
  425. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_CCDATE',false) );
  426. return False;
  427. }
  428. if (!$is_test) {
  429. $payment_number = ereg_replace(" |-", "", $_SESSION['ccdata']['order_payment_number']);
  430. if ($payment_number == "4111111111111111") {
  431. $vmLogger->warning( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_TEST',false) );
  432. return False;
  433. }
  434. }
  435. if(!empty($_SESSION['ccdata']['need_card_code']) && empty($_SESSION['ccdata']['credit_card_code'])) {
  436. $vmLogger->err( $VM_LANG->_('PHPSHOP_CUSTOMER_CVV2_ERROR',false) );
  437. return False;
  438. }
  439. if(!$_SESSION['ccdata']['order_payment_expire_month']) {
  440. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_CCMON',false) );
  441. return False;
  442. }
  443. if(!$_SESSION['ccdata']['order_payment_expire_year']) {
  444. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_CCYEAR',false) );
  445. return False;
  446. }
  447. $date = getdate( time() );
  448. if ($_SESSION['ccdata']['order_payment_expire_year'] < $date["year"] or
  449. ($_SESSION['ccdata']['order_payment_expire_year'] == $date["year"] and
  450. $_SESSION['ccdata']['order_payment_expire_month'] < $date["mon"])) {
  451. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_CCDATE_INV',false) );
  452. return False;
  453. }
  454. return True;
  455. }
  456. elseif ($dbp->f("enable_processor") == "B") {
  457. $_SESSION['ccdata']['creditcard_code'] = "";
  458. $_SESSION['ccdata']['order_payment_name'] = "";
  459. $_SESSION['ccdata']['order_payment_number'] = "";
  460. $_SESSION['ccdata']['order_payment_expire_month'] = "";
  461. $_SESSION['ccdata']['order_payment_expire_year'] = "";
  462. // Bank Account
  463. require_once( CLASSPATH . 'ps_user.php' );
  464. $dbu =& ps_user::getUserInfo( $auth["user_id"], array( 'bank_account_holder','bank_iban','bank_account_nr','bank_sort_code','bank_name' ) );
  465. if($_SERVER['REMOTE_ADDR'] == '67.161.25.236'){
  466. }
  467. //Organic Mod: We want it to replace if fields are filled in
  468. //if ( $dbu->f("bank_account_holder") == "" || $dbu->f("bank_account_nr") =="" ) {
  469. if( !empty($d['bank_account_holder']) && !empty($d['bank_account_nr'])) {
  470. // Insert the given data
  471. $fields = array( 'bank_account_holder' => $d['bank_account_holder'],
  472. 'bank_account_nr' => $d['bank_account_nr'],
  473. 'bank_sort_code' => $d['bank_sort_code'],
  474. 'bank_name' => $d['bank_name'],
  475. 'bank_iban' => $d['bank_iban']
  476. );
  477. ps_user::setUserInfo( $fields, $auth["user_id"] );
  478. $dbu =& ps_user::getUserInfo( $auth["user_id"], array( 'bank_account_holder','bank_iban','bank_account_nr','bank_sort_code','bank_name' ) );
  479. }
  480. else {
  481. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_USER_DATA',false) );
  482. return False;
  483. }
  484. //}
  485. if ($dbu->f("bank_account_holder") == ""){
  486. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_BA_HOLDER_NAME',false) );
  487. return False;
  488. }
  489. if (($dbu->f("bank_iban") == "") and
  490. ($dbu->f("bank_account_nr") =="")) {
  491. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_IBAN',false) );
  492. return False;
  493. }
  494. if ($dbu->f("bank_iban") == "") {
  495. if ($dbu->f("bank_account_nr") == ""){
  496. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_BA_NUM',false) );
  497. return False;
  498. }
  499. if ($dbu->f("bank_sort_code") == ""){
  500. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_BANK_SORT',false) );
  501. return False;
  502. }
  503. if ($dbu->f("bank_name") == ""){
  504. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_BANK_NAME',false) );
  505. return False;
  506. }
  507. }
  508. }
  509. else {
  510. $_SESSION['ccdata']['creditcard_code'] = '';
  511. $_SESSION['ccdata']['order_payment_name'] = "";
  512. $_SESSION['ccdata']['order_payment_number'] = "";
  513. $_SESSION['ccdata']['order_payment_expire_month'] = "";
  514. $_SESSION['ccdata']['order_payment_expire_year'] = "";
  515. }
  516. // Enter additional Payment check procedures here if neccessary
  517. return True;
  518. }
  519. /**
  520. * Update order details
  521. * CURRENTLY UNUSED
  522. *
  523. * @param array $d
  524. * @return boolean
  525. */
  526. function update(&$d) {
  527. global $vmLogger;
  528. $db = new ps_DB;
  529. $timestamp = time();
  530. if ($this->validate_update($d)) {
  531. return True;
  532. }
  533. else {
  534. $vmLogger->err( $this->error );
  535. return False;
  536. }
  537. }
  538. /**
  539. * Control Function for the Checkout Process
  540. * @author Ekkhard Domning
  541. * @author soeren
  542. * @param array $d
  543. * @return boolean
  544. */
  545. function process(&$d) {
  546. global $checkout_this_step, $sess,$VM_LANG, $vmLogger;
  547. $ccdata = array();
  548. if( empty($d["checkout_this_step"]) || !is_array(@$d["checkout_this_step"])) {
  549. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_VALID_STEP',false) );
  550. return false;
  551. }
  552. foreach($d["checkout_this_step"] as $checkout_this_step) {
  553. switch($checkout_this_step) {
  554. case 'CHECK_OUT_GET_FINAL_BASKET' :
  555. break;
  556. case 'CHECK_OUT_GET_SHIPPING_ADDR' :
  557. // The User has choosen a Shipping address
  558. if (empty($d["ship_to_info_id"])) {
  559. $vmLogger->err( $VM_LANG->_('PHPSHOP_CHECKOUT_ERR_NO_SHIPTO',false) );
  560. unset( $_POST['checkout_this_step']);
  561. return False;
  562. }
  563. break;
  564. case 'CHECK_OUT_GET_SHIPPING_METHOD':
  565. // The User has choosen a Shipping method
  566. if (!$this->validate_shipping_method($d)) {
  567. unset( $_POST['checkout_this_step']);
  568. return false;
  569. }
  570. break;
  571. case 'CHECK_OUT_GET_PAYMENT_METHOD':
  572. // The User has choosen a payment method
  573. $_SESSION['ccdata']['order_payment_name'] = @$d['order_payment_name'];
  574. // VISA, AMEX, DISCOVER....
  575. $_SESSION['ccdata']['creditcard_code'] = @$d['creditcard_code'];
  576. $_SESSION['ccdata']['order_payment_number'] = @$d['order_payment_number'];
  577. $_SESSION['ccdata']['order_payment_expire_month'] = @$d['order_payment_expire_month'];
  578. $_SESSION['ccdata']['order_payment_expire_year'] = @$d['order_payment_expire_year'];
  579. // 3-digit Security Code (CVV)
  580. $_SESSION['ccdata']['credit_card_code'] = @$d['credit_card_code'];
  581. if (!$this->validate_payment_method($d, true)) { //Change false to true to Let the user play with the VISA Testnumber
  582. unset( $_POST['checkout_this_step']);
  583. return false;
  584. }
  585. break;
  586. case 'CHECK_OUT_GET_FINAL_CONFIRMATION':
  587. // The User wants to order now, validate everything, if OK than Add immeditialtly
  588. return( $this->add( $d ) );
  589. default:
  590. $vmLogger->crit( "CheckOut step ($checkout_this_step) is undefined!" );
  591. return false;
  592. } // end switch
  593. }
  594. return true;
  595. } // end function process
  596. /**
  597. * Prints the List of all shipping addresses of a user
  598. *
  599. * @param unknown_type $user_id
  600. * @param unknown_type $name
  601. * @param unknown_type $value
  602. */
  603. function ship_to_addresses_radio($user_id, $name, $value) {
  604. echo ps_checkout::list_addresses( $user_id, $name, $value );
  605. }
  606. /**
  607. * Creates a Radio List of all shipping addresses of a user
  608. *
  609. * @param int $user_id
  610. * @param string $name
  611. * @param string $value
  612. */
  613. function list_addresses( $user_id, $name, $value ) {
  614. global $sess,$VM_LANG;
  615. $db = new ps_DB;
  616. /* Select all the ship to information for this user id and
  617. * order by modification date; most recently changed to oldest
  618. */
  619. $q = "SELECT * from #__{vm}_user_info WHERE ";
  620. $q .= "user_id=" . (int)$user_id . ' ';
  621. $q .= "AND address_type='BT'";
  622. $db->query($q);
  623. $db->next_record();
  624. $bt_user_info_id = $db->f("user_info_id");
  625. $q = "SELECT * FROM #__{vm}_user_info i ";
  626. $q .= "INNER JOIN #__{vm}_country c ON (i.country=c.country_3_code) ";
  627. $q .= "LEFT JOIN #__{vm}_state s ON (i.state=s.state_2_code AND s.country_id=c.country_id) ";
  628. $q .= "WHERE user_id =" . (int)$user_id . ' ';
  629. $q .= "AND address_type = 'ST' ";
  630. $q .= "ORDER by address_type_name, mdate DESC";
  631. $db->query($q);
  632. $theme = vmTemplate::getInstance();
  633. $theme->set_vars(array('db' => $db,
  634. 'user_id' => $user_id,
  635. 'name' => $name,
  636. 'value' => $value,
  637. 'bt_user_info_id' => $bt_user_info_id,
  638. )
  639. );
  640. echo $theme->fetch( 'checkout/list_shipto_addresses.tpl.php');
  641. }
  642. /**
  643. * Fetches the address information for the currently logged in user
  644. *
  645. * @param string $address_type Can be BT (Bill To) or ST (Shipto address)
  646. */
  647. function display_address($address_type='BT') {
  648. $auth = $_SESSION['auth'];
  649. $address_type = $address_type == 'BT' ? $address_type : 'ST';
  650. $db = new ps_DB;
  651. $q = "SELECT * FROM #__{vm}_user_info i ";
  652. $q .= "INNER JOIN #__{vm}_country c ON (i.country=c.country_3_code OR i.country=c.country_2_code) ";
  653. $q .= "LEFT JOIN #__{vm}_state s ON (i.state=s.state_2_code AND s.country_id=c.country_id) ";
  654. $q .= "WHERE user_id='" . $auth["user_id"] . "' ";
  655. $q .= "AND address_type='BT'";
  656. $db->query($q);
  657. $db->next_record();
  658. $theme = new $GLOBALS['VM_THEMECLASS']();
  659. $theme->set('db', $db );
  660. return $theme->fetch('checkout/customer_info.tpl.php');
  661. }
  662. /**
  663. * Lists Shipping Methods of all published Shipping Modules
  664. *
  665. * @param string $ship_to_info_id
  666. * @param string $shipping_method_id
  667. */
  668. function list_shipping_methods( $ship_to_info_id=null, $shipping_method_id=null ) {
  669. global $PSHOP_SHIPPING_MODULES, $vmLogger, $auth, $weight_total;
  670. if( empty( $ship_to_info_id )) {
  671. // Get the Bill to user_info_id
  672. $database = new ps_DB();
  673. $database->setQuery( "SELECT user_info_id FROM #__{vm}_user_info WHERE user_id=".$auth['user_id']." AND address_type='BT'" );
  674. $vars["ship_to_info_id"] = $_REQUEST['ship_to_info_id'] = $database->loadResult();
  675. } else {
  676. $vars['ship_to_info_id'] = $ship_to_info_id;
  677. }
  678. $vars['shipping_rate_id'] = $shipping_method_id;
  679. $vars["weight"] = $weight_total;
  680. $vars['zone_qty'] = vmRequest::getInt( 'zone_qty', 0 );
  681. $i = 0;
  682. $theme = new $GLOBALS['VM_THEMECLASS']();
  683. $theme->set_vars(array('vars' => $vars,
  684. 'PSHOP_SHIPPING_MODULES' => $PSHOP_SHIPPING_MODULES
  685. )
  686. );
  687. echo $theme->fetch( 'checkout/list_shipping_methods.tpl.php');
  688. }
  689. /**
  690. * Lists the payment methods of all available payment modules
  691. * @static
  692. * @param int $payment_method_id
  693. */
  694. function list_payment_methods( $payment_method_id=0 ) {
  695. global $order_total, $sess, $VM_CHECKOUT_MODULES, $VB_STAGE_PAY_METHODS, $page, $ps_booking;
  696. $ps_vendor_id = $_SESSION['ps_vendor_id'];
  697. $auth = $_SESSION['auth'];
  698. $ship_to_info_id = vmGet( $_REQUEST, 'ship_to_info_id' );
  699. $shipping_rate_id = vmGet( $_REQUEST, 'shipping_rate_id' );
  700. require_once(CLASSPATH . 'ps_payment_method.php');
  701. $ps_payment_method = new ps_payment_method;
  702. require_once( CLASSPATH. 'ps_creditcard.php' );
  703. $ps_creditcard = new ps_creditcard();
  704. /**
  705. * VirtueBook:
  706. * Only show the payment stages relating to multi-stage payments
  707. * if we are on the order.payment_list page
  708. * */
  709. if(isset($VB_STAGE_PAY_METHODS) && count($VB_STAGE_PAY_METHODS) && $page == 'order.payment_list'){
  710. $stage_pay_methods = $VB_STAGE_PAY_METHODS;
  711. }else{
  712. $stage_pay_methods = array();
  713. }
  714. // Do we have Credit Card Payments?
  715. $db_cc = new ps_DB;
  716. $q = "SELECT * from #__{vm}_payment_method,#__{vm}_shopper_group WHERE ";
  717. $q .= "#__{vm}_payment_method.shopper_group_id=#__{vm}_shopper_group.shopper_group_id ";
  718. $q .= "AND (#__{vm}_payment_method.shopper_group_id='".$auth['shopper_group_id']."' ";
  719. $q .= "OR #__{vm}_shopper_group.default='1') ";
  720. $q .= "AND (enable_processor='' OR enable_processor='Y') ";
  721. $q .= (count($stage_pay_methods) ? "AND payment_method_id IN (".implode(',',$stage_pay_methods).") " : "AND payment_enabled='Y' ");
  722. $q .= "AND #__{vm}_payment_method.vendor_id='$ps_vendor_id' ";
  723. $q .= " ORDER BY list_order";
  724. $db_cc->query($q);
  725. if ($db_cc->num_rows()) {
  726. $cc_payments=true;
  727. }
  728. else {
  729. $cc_payments=false;
  730. }
  731. $count = 0;
  732. $db_nocc = new ps_DB;
  733. $q = "SELECT * from #__{vm}_payment_method,#__{vm}_shopper_group WHERE ";
  734. $q .= "#__{vm}_payment_method.shopper_group_id=#__{vm}_shopper_group.shopper_group_id ";
  735. $q .= "AND (#__{vm}_payment_method.shopper_group_id='".$auth['shopper_group_id']."' ";
  736. $q .= "OR #__{vm}_shopper_group.default='1') ";
  737. $q .= "AND (enable_processor='B' OR enable_processor='N' OR enable_processor='P') ";
  738. $q .= (count($stage_pay_methods) ? "AND payment_method_id IN (".implode(',',$stage_pay_methods).") " : "AND payment_enabled='Y' ");
  739. $q .= "AND #__{vm}_payment_method.vendor_id='$ps_vendor_id' ";
  740. //Only show paypal if owner booking payments if false or there is no payment id
  741. if(!$ps_booking->payment_id || @VB_OWNER_BOOKING_PAYMENTS == 0){
  742. $q .= "AND #__{vm}_payment_method.payment_class != 'ps_paypal' ";
  743. }
  744. $q .= " ORDER BY list_order";
  745. $db_nocc->query($q);
  746. if ($db_nocc->next_record()) {
  747. $nocc_payments=true;
  748. $first_payment_method_id = $db_nocc->f("payment_method_id");
  749. $count = $db_nocc->num_rows();
  750. $db_nocc->reset();
  751. }
  752. else {
  753. $nocc_payments=false;
  754. }
  755. // Redirect to the last step when there's only one payment method
  756. if( $VM_CHECKOUT_MODULES['CHECK_OUT_GET_PAYMENT_METHOD']['order'] != $VM_CHECKOUT_MODULES['CHECK_OUT_GET_FINAL_CONFIRMATION']['order'] ) {
  757. if ($count <= 1 && $cc_payments==false) {
  758. vmRedirect($sess->url(SECUREURL.basename($_SERVER['PHP_SELF'])."?page=checkout.index&payment_method_id=$first_payment_method_id&ship_to_info_id=$ship_to_info_id&shipping_rate_id=".urlencode($shipping_rate_id)."&checkout_stage=".$VM_CHECKOUT_MODULES['CHECK_OUT_GET_FINAL_CONFIRMATION']['order'], false, false ),"");
  759. }
  760. elseif( isset($order_total) && $order_total <= 0.00 ) {
  761. // In case the order total is less than or equal zero, we don't need a payment method
  762. vmRedirect($sess->url(SECUREURL.basename($_SERVER['PHP_SELF'])."?page=checkout.index&ship_to_info_id=$ship_to_info_id&shipping_rate_id=".urlencode($shipping_rate_id)."&checkout_stage=".$VM_CHECKOUT_MODULES['CHECK_OUT_GET_FINAL_CONFIRMATION']['order'], false, false),"");
  763. }
  764. }
  765. $theme = new $GLOBALS['VM_THEMECLASS']();
  766. $theme->set_vars(array('db_nocc' => $db_nocc,
  767. 'db_cc' => $db_cc,
  768. 'nocc_payments' => $nocc_payments,
  769. 'payment_method_id' => $payment_method_id,
  770. 'first_payment_method_id' => $first_payment_method_id,
  771. 'count' => $count,
  772. 'cc_payments' => $cc_payments,
  773. 'ps_creditcard' => $ps_creditcard,
  774. 'ps_payment_method' => $ps_payment_method
  775. )
  776. );
  777. echo $theme->fetch( 'checkout/list_payment_methods.tpl.php');
  778. }
  779. /**
  780. * This is the main function which stores the order information in the database
  781. *
  782. * @author gday, soeren, many others!
  783. * @param array $d The REQUEST/$vars array
  784. * @return boolean
  785. */
  786. function add( &$d ) {
  787. global $order_tax_details, $afid, $VM_LANG, $auth, $my, $mosConfig_offset,
  788. $vmLogger, $vmInputFilter, $discount_factor, $ps_booking;
  789. $ps_vendor_id = $_SESSION["ps_vendor_id"];
  790. $auth = $_SESSION['auth'];
  791. $cart = $_SESSION['cart'];
  792. require_once(CLASSPATH. 'ps_payment_method.php' );
  793. $ps_payment_method = new ps_payment_method;
  794. require_once(CLASSPATH. 'ps_product.php' );
  795. $ps_product= new ps_product;
  796. require_once(CLASSPATH.'ps_cart.php');
  797. $ps_cart = new ps_cart;
  798. if (AFFILIATE_ENABLE == '1') {
  799. require_once(CLASSPATH.'ps_affiliate.php');
  800. $ps_affiliate = new ps_affiliate;
  801. }
  802. $db = new ps_DB;
  803. //Validate the booking
  804. if (!$ps_booking->process(1,0)) {
  805. $_SESSION['last_page'] = "booking.index";
  806. $_REQUEST["checkout_next_step"] = CHECK_OUT_GET_FINAL_CONFIRMATION;
  807. return False;
  808. }
  809. /* Set the order number */
  810. $order_number = $this->get_order_number();
  811. $totals = $this->calc_order_totals( $d );
  812. extract( $totals );
  813. /**
  814. * Virtuebook: Add booking totals to order totals
  815. *
  816. */
  817. $payment_stages = $ps_booking->getStagePayment($order_total);
  818. /*** Virtuebook End ***/
  819. $timestamp = time() + ($mosConfig_offset*60*60);
  820. // calculate the unix timestamp for the specified expiration date
  821. // default the day to the 1st
  822. $expire_timestamp = @mktime(0,0,0,$_SESSION["ccdata"]["order_payment_expire_month"], 1,$_SESSION["ccdata"]["order_payment_expire_year"]);
  823. $_SESSION["ccdata"]["order_payment_expire"] = $expire_timestamp;
  824. //Check that the form validates and that the booking status is not set to 1
  825. //!$this->validate_form($d) ||
  826. if (!$ps_booking->status) {
  827. return false;
  828. }
  829. if (!$this->validate_add($d)) {
  830. return false;
  831. }
  832. // make sure Total doesn't become negative
  833. if( $order_total < 0 ) $order_total = 0;
  834. $order_total = round( $order_total, 2);
  835. $vmLogger->debug('-- Checkout Debug--
  836. Subtotal: '.$order_subtotal.'
  837. Taxable: '.$order_taxable.'
  838. Payment Discount: '.$payment_discount.'
  839. Coupon Discount: '.$coupon_discount.'
  840. Shipping: '.$order_shipping.'
  841. Shipping Tax : '.$order_shipping_tax.'
  842. Tax : '.$order_tax.'
  843. ------------------------
  844. Order Total: '.$order_total.'
  845. ----------------------------'
  846. );
  847. // Check to see if Payment Class File exists
  848. $payment_class = $ps_payment_method->get_field($d["payment_method_id"], "payment_class");
  849. $enable_processor = $ps_payment_method->get_field($d["payment_method_id"], "enable_processor");
  850. //Set a hasPaid variable that will control whether to send a success email later
  851. $hasPaid = 0;
  852. if (file_exists(CLASSPATH . "payment/$payment_class.php") ) {
  853. if( !class_exists( $payment_class )) {
  854. include( CLASSPATH. "payment/$payment_class.php" );
  855. }
  856. $_PAYMENT = new $payment_class();
  857. if (!$_PAYMENT->process_payment($order_number, $order_total_due, $d, $payment_stages)) {
  858. //$vmLogger->err( $VM_LANG->_('PHPSHOP_PAYMENT_ERROR',false)." ($payment_class)" );
  859. $_SESSION['last_page'] = "checkout.index";
  860. $_REQUEST["checkout_next_step"] = CHECK_OUT_GET_PAYMENT_METHOD;
  861. return False;
  862. }
  863. $hasPaid = 1;
  864. }
  865. else {
  866. $d["order_payment_log"] = $VM_LANG->_('PHPSHOP_CHECKOUT_MSG_LOG');
  867. }
  868. // Remove the Coupon, because it is a Gift Coupon and now is used!!
  869. if( @$_SESSION['coupon_type'] == "gift" ) {
  870. $d['coupon_id'] = $_SESSION['coupon_id'];
  871. include_once( CLASSPATH.'ps_coupon.php' );
  872. ps_coupon::remove_coupon_code( $d );
  873. }
  874. // Get the IP Address
  875. if (!empty($_SERVER['REMOTE_ADDR'])) {
  876. $ip = $_SERVER['REMOTE_ADDR'];
  877. }
  878. else {
  879. $ip = 'unknown';
  880. }
  881. // Collect all fields and values to store them!
  882. $fields = array(
  883. 'user_id' => $auth["user_id"],
  884. 'vendor_id' => $ps_vendor_id,
  885. 'order_number' => $order_number,
  886. 'user_info_id' => $d["ship_to_info_id"],
  887. 'ship_method_id' => @urldecode($d["shipping_rate_id"]),
  888. 'order_total' => $order_total,
  889. 'order_subtotal' => $order_subtotal,
  890. 'order_tax' => $order_tax,
  891. 'order_tax_details' => serialize($order_tax_details),
  892. 'order_shipping' => $order_shipping,
  893. 'order_shipping_tax' => $order_shipping_tax,
  894. 'order_discount' => $payment_discount,
  895. 'coupon_discount' => $coupon_discount,
  896. 'coupon_code' => @$_SESSION['coupon_code'],
  897. 'order_currency' => $GLOBALS['product_currency'],
  898. 'order_status' => 'P',
  899. 'cdate' => $timestamp,
  900. 'mdate' => $timestamp,
  901. 'customer_note' => htmlspecialchars(strip_tags($d['customer_note']), ENT_QUOTES ),
  902. 'ip_address' => $ip
  903. );
  904. // Insert the main order information
  905. $db->buildQuery( 'INSERT', '#__{vm}_orders', $fields );
  906. $result = $db->query();
  907. $d["order_id"] = $order_id = $db->last_insert_id();
  908. if( $result === false || empty( $order_id )) {
  909. $vmLogger->crit( 'Adding the Order into the Database failed! User ID: '.$auth["user_id"] );
  910. return false;
  911. }
  912. // Insert the initial Order History.
  913. $mysqlDatetime = date("Y-m-d G:i:s", $timestamp);
  914. $fields = array(
  915. 'order_id' => $order_id,
  916. 'order_status_code' => 'P',
  917. 'date_added' => $mysqlDatetime,
  918. 'customer_notified' => 1,
  919. 'comments' => '',
  920. 'booking_serialized' => serialize($ps_booking)
  921. );
  922. $db->buildQuery( 'INSERT', '#__{vm}_order_history', $fields );
  923. $db->query();
  924. /**
  925. * Virtuebook: Save the booking data
  926. */
  927. $fields = array('order_id' => $order_id,
  928. 'property_id' => $ps_booking->property_id,
  929. 'people' => $ps_booking->people,
  930. 'arrival' => $ps_booking->dateFrom,
  931. 'departure' => $ps_booking->dateTo,
  932. 'total' => $ps_booking->total,
  933. 'subtotal' => $ps_booking->subtotal,
  934. 'original' => $ps_booking->original,
  935. 'tax_total' => $ps_booking->tax,
  936. 'tax_state' => $ps_booking->tax_state,
  937. 'tax_resort' => $ps_booking->tax_resort,
  938. 'discounts' => $ps_booking->adv_discount['discount_total'],
  939. 'discount_details' => serialize($ps_booking->adv_discount),
  940. 'insurance' => $ps_booking->securityDeposit,
  941. 'cleaning' => $ps_booking->cleaning
  942. );
  943. $db->buildQuery( 'INSERT', '#__{vm}_order_booking', $fields );
  944. if (!$db->query()) {
  945. $vmLogger->crit( 'There was a problem saving your booking. The booking reference is: '.$order_id.'. The Error Information is: '.$db->getErrorMsg());
  946. return false;
  947. }
  948. /* Virtuebook End */
  949. /**
  950. * Insert the Order payment info
  951. */
  952. $payment_number = ereg_replace(" |-", "", @$_SESSION['ccdata']['order_payment_number']);
  953. $d["order_payment_code"] = @$_SESSION['ccdata']['credit_card_code'];
  954. /**
  955. * Virtuebook: Loop through the stage payment info
  956. */
  957. foreach($payment_stages->stages as $k => &$payment){
  958. if(is_object($payment)){
  959. // Payment number is encrypted using mySQL encryption functions.
  960. $fields = array(
  961. 'order_id' => $order_id,
  962. 'payment_amount' => $payment->payment_amount,
  963. 'payment_due' => $payment->payment_due,
  964. 'payment_stage' => $payment->payment_stage
  965. );
  966. $specialfield = array();
  967. //Check if the payment is due
  968. if($payment->is_due){
  969. $payment->payment_method_id = $d["payment_method_id"];
  970. $fields['payment_submitted'] = $payment->payment_submitted;
  971. $fields['payment_cleared'] = $payment->payment_cleared;
  972. $fields['payment_method_id'] = $payment->payment_method_id;
  973. $fields['order_payment_log'] = @$d["order_payment_log"];
  974. $fields['order_payment_trans_id'] = $vmInputFilter->safeSQL( @$d["order_payment_trans_id"] );
  975. if( !empty( $payment_number ) && VM_STORE_CREDITCARD_DATA == '1' ) {
  976. // Store Credit Card Information only if the Store Owner has decided to do so
  977. $fields['order_payment_code'] = $d["order_payment_code"];
  978. $fields['order_payment_expire'] = @$_SESSION["ccdata"]["order_payment_expire"];
  979. $fields['order_payment_name'] = @$_SESSION["ccdata"]["order_payment_name"];
  980. $fields['order_payment_number'] = VM_ENCRYPT_FUNCTION."( '$payment_number','" . ENCODE_KEY . "')";
  981. $specialfield = array('order_payment_number');
  982. }
  983. }
  984. //Add to DB
  985. $db->buildQuery( 'INSERT', '#__{vm}_order_payment', $fields, '', $specialfield );
  986. if(!$db->query()){
  987. $vmLogger->crit( 'There was a problem saving your bookings payment information. The booking reference is: '.$order_id.'. The Error Information is: '.$db->getErrorMsg());
  988. }
  989. }
  990. }
  991. //Store in the session for use in the thankyou page payment extra_info processing
  992. $_SESSION['payment_stages'] = $payment_stages;
  993. /**
  994. * Insert the User Billto & Shipto Info
  995. */
  996. // First: get all the fields from the user field list to copy them from user_info into the order_user_info
  997. $fields = array();
  998. require_once( CLASSPATH . 'ps_userfield.php' );
  999. $userfields = ps_userfield::getUserFields('', false, '', true, true );
  1000. foreach ( $userfields as $field ) {
  1001. $fields[] = $field->name;
  1002. }
  1003. $fieldstr = str_replace( 'email', 'user_email', implode( ',', $fields ));
  1004. // Save current Bill To Address
  1005. $q = "INSERT INTO `#__{vm}_order_user_info`
  1006. (`order_info_id`,`order_id`,`user_id`,address_type, ".$fieldstr.") ";
  1007. $q .= "SELECT NULL, '$order_id', '".$auth['user_id']."', address_type, ".$fieldstr." FROM #__{vm}_user_info WHERE user_id='".$auth['user_id']."' AND address_type='BT'";
  1008. $db->query( $q );
  1009. // Save current Ship to Address if applicable
  1010. $q = "INSERT INTO `#__{vm}_order_user_info`
  1011. (`order_info_id`,`order_id`,`user_id`,address_type, ".$fieldstr.") ";
  1012. $q .= "SELECT NULL, '$order_id', '".$auth['user_id']."', address_type, ".$fieldstr." FROM #__{vm}_user_info WHERE user_id='".$auth['user_id']."' AND user_info_id='".$d['ship_to_info_id']."' AND address_type='ST'";
  1013. $db->query( $q );
  1014. /**
  1015. * Insert all Products from the Cart into order line items;
  1016. * one row per product in the cart
  1017. */
  1018. $dboi = new ps_DB;
  1019. for($i = 0; $i < $cart["idx"]; $i++) {
  1020. $r = "SELECT product_id,product_in_stock,product_sales,product_parent_id,product_sku,product_name ";
  1021. $r .= "FROM #__{vm}_product WHERE product_id='".$cart[$i]["product_id"]."'";
  1022. $dboi->query($r);
  1023. $dboi->next_record();
  1024. $product_price_arr = $ps_product->get_adjusted_attribute_price($cart[$i]["product_id"], $cart[$i]["description"]);
  1025. $product_price = $GLOBALS['CURRENCY']->convert( $product_price_arr["product_price"], $product_price_arr["product_currency"] );
  1026. if( empty( $_SESSION['product_sess'][$cart[$i]["product_id"]]['tax_rate'] )) {
  1027. $my_taxrate = $ps_product->get_product_taxrate($cart[$i]["product_id"] );
  1028. }
  1029. else {
  1030. $my_taxrate = $_SESSION['product_sess'][$cart[$i]["product_id"]]['tax_rate'];
  1031. }
  1032. // Attribute handling
  1033. $product_parent_id = $dboi->f('product_parent_id');
  1034. $description = '';
  1035. if( $product_parent_id > 0 ) {
  1036. $db_atts = $ps_product->attribute_sql( $dboi->f('product_id'), $product_parent_id );
  1037. while( $db_atts->next_record()) {
  1038. $description .= $db_atts->f('attribute_name').': '.$db_atts->f('attribute_value').'; ';
  1039. }
  1040. }
  1041. $description .= $ps_product->getDescriptionWithTax($_SESSION['cart'][$i]["description"], $dboi->f('product_id'));
  1042. $product_final_price = round( ($product_price *($my_taxrate+1)), 2 );
  1043. $vendor_id = $ps_vendor_id;
  1044. $fields = array('order_id' => $order_id,
  1045. 'user_info_id' => $d["ship_to_info_id"],
  1046. 'vendor_id' => $vendor_id,
  1047. 'product_id' => $cart[$i]["product_id"],
  1048. 'order_item_sku' => $dboi->f("product_sku"),
  1049. 'order_item_name' => $dboi->f("product_name"),
  1050. 'product_quantity' => $cart[$i]["quantity"],
  1051. 'product_item_price' => $product_price,
  1052. 'product_final_price' => $product_final_price,
  1053. 'order_item_currency' => $GLOBALS['product_currency'],
  1054. 'order_status' => 'P',
  1055. 'product_attribute' => $description,
  1056. 'cdate' => $timestamp,
  1057. 'mdate' => $timestamp
  1058. );
  1059. $db->buildQuery( 'INSERT', '#__{vm}_order_item', $fields );
  1060. $db->query();
  1061. // Update Stock Level and Product Sales, decrease - no matter if in stock or not!
  1062. $q = "UPDATE #__{vm}_product ";
  1063. $q .= "SET product_in_stock = product_in_stock - ".(int)$cart[$i]["quantity"];
  1064. $q .= " WHERE product_id = '" . $cart[$i]["product_id"]. "'";
  1065. $db->query($q);
  1066. $q = "UPDATE #__{vm}_product ";
  1067. $q .= "SET product_sales= product_sales + ".(int)$cart[$i]["quantity"];
  1068. $q .= " WHERE product_id='".$cart[$i]["product_id"]."'";
  1069. $db->query($q);
  1070. }
  1071. ######## BEGIN DOWNLOAD MOD ###############
  1072. if( ENABLE_DOWNLOADS == "1" ) {
  1073. require_once( CLASSPATH.'ps_order.php');
  1074. for($i = 0; $i < $cart["idx"]; $i++) {
  1075. $params = array('product_id' => $cart[$i]["product_id"], 'order_id' => $order_id, 'user_id' => $auth["user_id"] );
  1076. ps_order::insert_downloads_for_product( $params );
  1077. if( @VM_DOWNLOADABLE_PRODUCTS_KEEP_STOCKLEVEL == '1' ) {
  1078. // Update the product stock level back to where it was.
  1079. $q = "UPDATE #__{vm}_product ";
  1080. $q .= "SET product_in_stock = product_in_stock + ".(int)$cart[$i]["quantity"];
  1081. $q .= " WHERE product_id = '" .(int)$cart[$i]["product_id"]. "'";
  1082. $db->query($q);
  1083. }
  1084. }
  1085. }
  1086. ################## END DOWNLOAD MOD ###########
  1087. if (AFFILIATE_ENABLE == '1') {
  1088. $ps_affiliate->register_sale($order_id);
  1089. }
  1090. // Export the order_id so the checkout complete page can get it
  1091. $d["order_id"] = $order_id;
  1092. /*
  1093. * Let the shipping module know which shipping method
  1094. * was selected. This way it can save any information
  1095. * it might need later to print a shipping label.
  1096. */
  1097. if( is_callable( array($this->_SHIPPING, 'save_rate_info') )) {
  1098. $this->_SHIPPING->save_rate_info($d);
  1099. }
  1100. // Now as everything else has been done, we can update
  1101. // the Order Status if the Payment Method is
  1102. // "Use Payment Processor", because:
  1103. // Payment Processors return false on any error
  1104. // Only completed payments return true!
  1105. $update_order = false;
  1106. if( $enable_processor == "Y" || $enable_processor == 'B' ) {
  1107. if( defined($_PAYMENT->payment_code.'_VERIFIED_STATUS')) {
  1108. $d['order_status'] = constant($_PAYMENT->payment_code.'_VERIFIED_STATUS');
  1109. $update_order = true;
  1110. }
  1111. } elseif( $order_total == 0.00 ) {
  1112. // If the Order Total is zero, we can confirm the order to automatically enable the download
  1113. $d['order_status'] = ENABLE_DOWNLOAD_STATUS;
  1114. $update_order = true;
  1115. }
  1116. if ( $update_order ) {
  1117. require_once(CLASSPATH."ps_order.php");
  1118. $ps_order =& new ps_order();
  1119. $ps_order->order_status_update($d);
  1120. }
  1121. //Remove bank account details
  1122. require_once( CLASSPATH . 'ps_user.php' );
  1123. $fields = array( 'bank_account_holder' => '',
  1124. 'bank_account_nr' => '',
  1125. 'bank_sort_code' => '',
  1126. 'bank_name' => '',
  1127. 'bank_iban' => ''
  1128. );
  1129. ps_user::setUserInfo( $fields, $auth["user_id"] );
  1130. // Send the e-mail confirmation messages
  1131. $this->email_receipt($order_id, '', $hasPaid);
  1132. // Reset the cart (=empty it)
  1133. $ps_cart->reset();
  1134. $_SESSION['savedcart']['idx']=0;
  1135. $ps_cart->saveCart();
  1136. // Unset the payment_method variables
  1137. $d["payment_method_id"] = "";
  1138. $d["order_payment_number"] = "";
  1139. $d["order_payment_expire"] = "";
  1140. $d["order_payment_name"] = "";
  1141. $d["credit_card_code"] = "";
  1142. // Clear the sensitive Session data
  1143. $_SESSION['ccdata']['order_payment_name'] = "";
  1144. $_SESSION['ccdata']['order_payment_number'] = "";
  1145. $_SESSION['ccdata']['order_payment_expire_month'] = "";
  1146. $_SESSION['ccdata']['order_payment_expire_year'] = "";
  1147. $_SESSION['ccdata']['credit_card_code'] = "";
  1148. $_SESSION['coupon_discount'] = "";
  1149. $_SESSION['coupon_id'] = "";
  1150. $_SESSION['coupon_redeemed'] = false;
  1151. $_POST["payment_method_id"] = "";
  1152. $_POST["order_payment_number"] = "";
  1153. $_POST["order_payment_expire"] = "";
  1154. $_POST["order_payment_name"] = "";
  1155. //Clear the booking data from the session
  1156. $ps_booking->removeSession();
  1157. if( empty($my->id) && !empty( $auth['user_id'])) {
  1158. require_once(CLASSPATH.'ps_user.php');
  1159. ps_user::logout();
  1160. }
  1161. return True;
  1162. }
  1163. /**
  1164. * Create an order number using the session id, session
  1165. * name, and the current unix timestamp.
  1166. *
  1167. * @return string
  1168. */
  1169. function get_order_number() {
  1170. global $auth;
  1171. /* Generated a unique order number */
  1172. $str = session_id();
  1173. $str .= (string)time();
  1174. $order_number = $auth['user_id'] .'_'. md5($str);
  1175. return substr($order_number, 0, 32);
  1176. }
  1177. /**
  1178. * Stores the md5 hash of the recent cart in the var _cartHash
  1179. *
  1180. */
  1181. function generate_cart_hash() {
  1182. $this->_cartHash = $this->get_new_cart_hash();
  1183. }
  1184. function get_order_total( &$d ) {
  1185. global $discount_factor;
  1186. $totals = $this->calc_order_totals($d);
  1187. return $totals['order_total'];
  1188. }
  1189. /**
  1190. * Calculates the current order totals and fills an array with all the values
  1191. *
  1192. * @param array $d
  1193. * @return array
  1194. */
  1195. function calc_order_totals( &$d ) {
  1196. global $discount_factor, $mosConfig_offset, $ps_booking;
  1197. $totals = array();
  1198. /* sets _subtotal */
  1199. $totals['order_subtotal'] = $tmp_subtotal = $this->calc_order_subtotal($d);
  1200. $totals['order_taxable'] = $this->calc_order_taxable($d);
  1201. /* DISCOUNT HANDLING */
  1202. if( !empty($_SESSION['coupon_discount']) ) {
  1203. $totals['coupon_discount'] = floatval($_SESSION['coupon_discount']);
  1204. }
  1205. else {
  1206. $totals['coupon_discount'] = 0.00;
  1207. }
  1208. // make sure Total doesn't become negative
  1209. if( $tmp_subtotal < 0 ) $totals['order_subtotal'] = $tmp_subtotal = 0;
  1210. if( $totals['order_taxable'] < 0 ) $totals['order_taxable'] = 0;
  1211. // from now on we have $order_tax_details
  1212. $d['order_tax'] = $totals['order_tax'] = round( $this->calc_order_tax($totals['order_taxable'], $d), 2 );
  1213. if( is_object($this->_SHIPPING) ) {
  1214. /* sets _shipping */
  1215. $d['order_shipping'] = $totals['order_shipping'] = round( $this->calc_order_shipping( $d ), 2 );
  1216. /* sets _shipping_tax
  1217. * btw: This is WEIRD! To get an exactly rounded value we have to convert
  1218. * the amount to a String and call "round" with the string. */
  1219. $d['order_shipping_tax'] = $totals['order_shipping_tax'] = round( strval($this->calc_order_shipping_tax($d)), 2 );
  1220. }
  1221. else {
  1222. $d['order_shipping'] = $totals['order_shipping'] = $totals['order_shipping_tax'] = $d['order_shipping_tax'] = 0.00;
  1223. }
  1224. if( !empty($d['payment_method_id'])) {
  1225. $totals['payment_discount'] = $d['payment_discount'] = $this->get_payment_discount($d['payment_method_id'], $tmp_subtotal);
  1226. } else {
  1227. $totals['payment_discount'] = $d['payment_discount'] = 0.00;
  1228. }
  1229. $d['order_total'] = $totals['order_total'] = $tmp_subtotal
  1230. + $totals['order_tax']
  1231. + $totals['order_shipping']
  1232. + $totals['order_shipping_tax'];
  1233. /**
  1234. * Virtuebook: add on order totals
  1235. */
  1236. $totals['order_subtotal'] += $ps_booking->subtotal;
  1237. $totals['order_total'] += $ps_booking->total;
  1238. $totals['order_tax'] += $ps_booking->tax;
  1239. $totals['order_taxable'] = $ps_booking->tax > 0 || $totals['order_taxable'];
  1240. /**
  1241. * Get the payment stages
  1242. */
  1243. $payment_stages = $ps_booking->getStagePayment($order_total, $d['payment_method_id']);
  1244. if(isset($payment_stages->amount_due)){
  1245. $totals['order_total_due'] = $payment_stages->amount_due - $totals['coupon_discount'];
  1246. }else{
  1247. $totals['order_total_due'] = $totals['order_total'] = $totals['order_total'] - $this->get_payment_discount($d['payment_method_id'], $totals['order_total']) - $totals['coupon_discount'];
  1248. }
  1249. return $totals;
  1250. }
  1251. /**
  1252. * Generates the md5 hash of the recent cart / checkout constellation
  1253. *
  1254. * @return unknown
  1255. */
  1256. function get_new_cart_hash() {
  1257. return md5( print_r( $_SESSION['cart'], true)
  1258. . vmGet($_REQUEST,'shipping_rate_id')
  1259. . vmGet($_REQUEST,'payment_method_id')
  1260. );
  1261. }
  1262. /**
  1263. * Returns the recent subtotal
  1264. *
  1265. * @param array $d
  1266. * @return float The current order subtotal
  1267. */
  1268. function get_order_subtotal( &$d ) {
  1269. if( $this->_subtotal === null ) {
  1270. $this->_subtotal = $this->calc_order_subtotal( $d );
  1271. }
  1272. else {
  1273. if( $this->_cartHash != $this->get_new_cart_hash() ) {
  1274. // Need to re-calculate the subtotal
  1275. $this->_subtotal = $this->calc_order_subtotal( $d );
  1276. }
  1277. }
  1278. return $this->_subtotal;
  1279. }
  1280. /**********************************************…

Large files files are truncated, but you can click here to view the full file